iappwebdev
iappwebdev

Reputation: 5910

Map routes with combined URL parameter

User can download price information PDFs located in a folder PriceInformations with subfolders specifying the document type, e.g.:

/PriceInformations/Clothes/Shoes.pdf
/PriceInformations/Clothes/Shirts.pdf
/PriceInformations/Toys/Games.pdf
/PriceInformations/Toys/Balls.pdf

Consider following action in Controller Document to download those PDFs:

// Filepath must be like 'Clothes\Shoes.pdf'
public ActionResult DownloadPDF(string filepath)
{
    string fullPath = Path.Combine(MyApplicationPath, filepath);

    FileStream fileStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read);

    return base.File(fileStream, "application/pdf");
}

To get a PDF document, my client wants URLs to be like:

/PriceInformations/Clothes/Shoes.pdf

I could easily create an overload function for this case:

public ActionResult DownloadPDF(string folder, string filename)
{
    return this.DownloadPDF(Path.Combine(folder, filename);
}

And map it like

routes.MapRoute(
    "DownloadPriceInformations",
    "DownloadPriceInformations/{folder}/{filename}",
    new
    {
        controller = "Document",
        action = "DownloadPDF"
    });

But I'm curious if it would be possible to work without an overload function and to map this case in RegisterRoutes in Global.asax, so to be able to create one single parameter out of of multiple parameters:

routes.MapRoute(
    "DownloadPriceInformations",
    "DownloadPriceInformations/{folder}/{filename}",
    new
    {
        controller = "Document",
        action = "DownloadPDF",
        // How to procede here to have a parameter like 'folder\filename'
        filepath = "{folder}\\{filename}"
    });

Question became a bit longer but I wanted to make sure, you get my desired result.

Upvotes: 2

Views: 1829

Answers (1)

Eilon
Eilon

Reputation: 25704

Sorry, this is not supported in ASP.NET routing. If you want multiple parameters in the route definition you'll have to add some code to the controller action to combine the folder and path name.

An alternative is to use a catch-all route:

routes.MapRoute(
    "DownloadPriceInformations",
    "DownloadPriceInformations/{*folderAndFile}",
    new
    {
        controller = "Document",
        action = "DownloadPDF"
    });

And the special {*folderAndFile} parameter will contain everything after the initial static text, including all the "/" characters (if any). You can then take in that parameter in your action method and it'll be a path like "clothes/shirts.pdf".

I should also note that from a security perspective you need to be absolutely certain that only allowed paths will be processed. If I pass in /web.config as the parameter, you must make sure that I can't download all your passwords and connection strings that are stored in your web.config file.

Upvotes: 2

Related Questions