Accept url as parameter in MVC action? - asp.net-mvc

I'm using ASP.NET MVC 3 and I would like to accept url as parameter for one of the action. But, I'm getting "HTTP Error 400 - Bad Request." error for the below example. How do I resolve this issue?
Example:
http://localhost:8343/http://google.com
Global.asax.cs:
routes.MapRoute(
"Default", // Route name
"{hostUrl}", // URL with parameters
new { controller = "Home", action = "Index", hostUrl = UrlParameter.Optional } // Parameter defaults
);

You need to use URL encoding for the parameter http://google.com.
So, navigate here:
http://localhost:8343/http%3A%2F%2Fgoogle.com
(I just used an online URL encoder tool.)

Use
HttpUtility.UrlEncode
or
Server.URLEncode
Depending where you are doing the encoding.

I fixed by following these steps.
Change Web project properties to "Use IIS Local Server" and check "Use IIS Express"
Add the following setting in Web.config inside :
<httpRuntime requestPathInvalidCharacters=""/>

Related

Url for pages in ASP.NET MVC4

Ok.is it possible to set url for the pages of type "localhost:5454/user/details/1" to localhost:5454/somenameofuser .. can i do it in mvc4? "somenameofuser" is an url for concrete page. I want to set this field to the class user. and this field would unikalnym..thanks for the help!
What is it you are trying to achieve? Explain it further. But as for my understanding, You could try and create a routing that will match a url of /somenameofuser
routes.MapRoute (
"Default", // Route name
"/{nameofuser}", // URL with parameters
new { controller = "Controller here", action = "Action here" } // Parameter defaults
);

Adding filename in url

I want to customize route in ASP.NET MVC.
With
#Url.Action("ViewDoc", "Home", new { FileName = "ABC.pdf" })
and
routes.MapRoute(
name: "",
url: "{controller}/{action}/{FileName}",
defaults: new
{
controller = "Home",
action = "ViewDoc",
FileName = UrlParameter.Optional
}
I get
http://localhost/Home/ViewDoc?FileName=ABC.pdf
How to get the below?
http://localhost/Home/ViewDoc/ABC.pdf
The code you have pasted is correct but the ordering in your route setup is probably wrong. Move the routes.MapRoute method to be above the default route and it should work as expected.
Regarding your 404 error:
I'm using the same kind of URL with a file name at the end and getting the same routing problem.
Just like you, I try to catch the call with a controller.
I think the problem is the URL is treated as a direct link to a file on the server and it will just try to go get the file instead of calling the controller. Not finding the file at the physical location suggested by the URL will trigger a 404 error.
The workaround I chose to use is adding a "/" character at the very end of the URL after the file name.
There are others.
I suggest you read this related question:
Dots in URL causes 404 with ASP.NET mvc and IIS
I was able get
localhost/Home/ViewDoc/ABC.pdf
with
public FileResult View(string FileName) {
and
routes.MapRoute( "", "Home/ViewDoc/{FileName}", new { controller = "Home", action = "ViewDoc" } );
For Error 404.0 added the below under
<add
name="AdfsMetadata"
path="/Home/ViewDocu/*"
verb="POST"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />

ASP.NET MVC 3: RouteExistingFiles = true seems to have no effect

I'm trying to understand how RouteExistingFiles works.
So I've created a new MVC 3 internet project (MVC 4 behaves the same way) and put a HTMLPage.html file to the Content folder of my project.
Now I went to the Global.Asax file and edited the RegisterRoutes function so it looks like this:
public static void RegisterRoutes(RouteCollection routes)
{
routes.RouteExistingFiles = true; //Look for routes before looking if a static file exists
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {controller = "Home", action = "Index", id = UrlParameter.Optional} // Parameter defaults
);
}
Now it should give me an error when I'm requesting a localhost:XXXX/Content/HTMLPage.html since there's no "Content" controller and the request definitely hits the default pattern. But instead I'm seeing my HTMLPage.
What am I doing wrong here?
Update:
I think I'll have to give up.
Even if I'm adding a route like this one:
routes.MapRoute("", "Content/{*anything}", new {controller = "Home", action = "Index"});
it still shows me the content of the HTMLPage.
When I request a url like ~/Content/HTMLPage I'm getting the Index page as expected, but when I add a file extenstion like .html or .txt the content is shown (or a 404 error if the file does not exist).
If anyone can check this in VS2012 please let me know what result you're getting.
Thank you.
To enabling routing for static files you must perform following steps.
In RouteConfig.cs enable routing for existing files
routes.RouteExistingFiles = true;
Add a route for your path ( Make sure specialized path are above generalized paths)
routes.MapRoute(
name: "staticFileRoute",
url: "Public/{file}/",
defaults: new { controller = "Home", action = "SomeAction" }
);
Next configure your application, so that request for static files are handeled by "TransferRequestHandler".In Webconfig under system.webServer>handlers add following entry.
<add name="MyCustomUrlHandler2" path="Public/*" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
The value of 'path' can be more generic or specific depending on your requirement. But i prefer it to be always very specific as per one's need. Keeping it very generic will block serving of other site specific resources such as .js or css files. For example if above is set as path="*", then request for even the css (inside the content folder) which is responsible for how your page would look will also end up in your Controller's action. Something that you will not like.
Visual Studio 2012 uses IIS Express. You need to tell IIS not to intercept requests for disk files before they are passed to the MVC routing system. You need set preCondition attribute to the empty string in config file:
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule"
preCondition="" />
In Win7/8 you can find config file on this path: %userprofile%\Documents\IISExpress\config\applicationhost.config
The RouteExistingFiles doesn't keep files from being viewed if there is no route for them, it just checks the routes before checking if the file exists. If there is no matching route, it will continue to check if there is a matching file.

ASP.NET MVC - Catch All Route And Default Route

In trying to get my application to produce 404 errors correctly, I have implemented a catch all route at the end of my route table, as shown below:
routes.MapRoute(
"NotFound", _
"{*url}", _
New With {.controller = "Error", .action = "PageNotFound"} _
)
However, to get this working, I had to remove the default route:
{controller}/action/{id}
But now that the default has been removed, most of my action links no longer work, and the only way I have found to get them working again is to add individual routes for each controller/action.
Is there a simpler way of doing this, rather than adding a route for each controller/action?
Is it possible to create a default route that still allows the catch all route to work if the user tries to navigate to an unknown route?
Use route constraints
In your case you should define your default route {controller}/{action}/{id} and put a constraint on it. Probably related to controller names or maybe even actions. Then put the catch all one after it and it should work just fine.
So when someone would request a resource that fails a constraint the catch-all route would match the request.
So. Define your default route with route constraints first and then the catch all route after it:
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new { controller = "Home|Settings|General|..." } // this is basically a regular expression
);
routes.MapRoute(
"NotFound",
"{*url}",
new { controller = "Error", action = "PageNotFound" }
);
//this catches all requests
routes.MapRoute(
"Error",
"{*.}",
new { controller = "PublicDisplay", action = "Error404" }
);
add this route at the end the routes table
Ah, the problem is your default route catches all 3 segment URLs. The issue here is that Routing runs way before we determine who is going to handle the request. Thus any three segment URL will match the default route, even if it ends up later that there's no controller to handle it.
One thing you can do is on your controller override the HandleMissingAction method. You should also use the tag to catch all 404 issues.
Well, what I have found is that there is no good way to do this. I have set the redirectMode property of the customErrors to ResponseRewrite.
<customErrors mode="On" defaultRedirect="~/Shared/Error" redirectMode="ResponseRewrite">
<error statusCode="404" redirect="~/Shared/PageNotFound"/>
</customErrors>
This gives me the sought after behavior, but does not display the formatted page.
To me this is poorly done, as far as SEO goes. However, I feel there is a solution that I am missing as SO does exactly what I want to happen. The URL remains on the failed page and throws a 404. Inspect stackoverflow.com/fail in Firebug.
My Solution is 2 steps.
I originally solved this problem by adding this function to my Global.asax.cs file:
protected void Application_Error(Object sender, EventArgs e)
Where I tried casting Server.GetLastError() to a HttpException, and then checked GetHttpCode.
This solution is detailed here:
ASP.NET MVC Custom Error Handling Application_Error Global.asax?
This isn't the original source where I got the code. However, this only catches 404 errors which have already been routed. In my case, that ment any 2 level URL.
for instance, these URLs would display the 404 page:
www.site.com/blah
www.site.com/blah/blah
however, www.site.com/blah/blah/blah would simply say page could not be found.
Adding your catch all route AFTER all of my other routes solved this:
routes.MapRoute(
"NotFound",
"{*url}",
new { controller = "Errors", action = "Http404" }
);
However, the NotFound route does not seem to route requests which have file extensions. This does work when they are captured by different routes.
I would recommend this as the most readable version. You need this in your RouteConfig.cs, and a controller called ErrorController.cs, containing an action 'PageNotFound'. This can return a view. Create a PageNotFound.cshtml, and it'll be returned in response to the 404:
routes.MapRoute(
name: "PageNotFound",
url: "{*url}",
defaults: new { controller = "Error", action = "PageNotFound" }
);
How to read this:
name: "PageNotFound"
= create a new route template, with the arbitrary name 'PageNotFound'
url:"{*url}"
= use this template to map all otherwise unhandled routes
defaults: new { controller = "Error", action = "PageNotFound" }
= define the action that an incorrect path will map to (the 'PageNotFound' Action Method in the Error controller). This is needed since an incorrectly entered path will not obviously not map to any action method
I tried all of the above pattern without luck, but finally found out that ASP.NET considered the url I used as a static file, so none of my request was hidding the single controller endpoint. I ended up adding this snipper to the web.config
<modules runAllManagedModulesForAllRequests="true"/>
And then use the below route match pattern, and it solved the issue:
routes.MapRoute(
name: "RouteForAnyRequest",
url: "{*url}",
defaults: new { controller = "RouteForAnyRequest", action = "PageNotFound" }
);

Can .net mvc routing cause JavaScript errors?

I am having a lot of trouble using routing infrastructure of asp.net mvc2. I have following routes registered in my global.asax file
routes.MapRoute(
"strict",
"{controller}.mvc/{docid}/{action}/{id}",
new { action = "Index", id = "", docid = "" },
new { docid = #"\d+"}
);
routes.MapRoute(
"default",
"{controller}.mvc/{action}/{id}",
new { action = "Index", id = "" },
new { docConstraint = new DocumentConstraint() }
);
The problem is with first route ("strict"). Three kind of urls can match first route. mycontroller/23/myaction, mycontroller/23/myaction/12 or mycontroller/23/mvaction/stringid. If I try to use this route without specifying value of id everything works fine for example:
Html.ActionLink("Link text", "ActionName", new{docid = 23});
Everything goes well, but if I use links like:
Html.ActionLink("Link text", "ActionName", new{docid = 23, id = 223})
This will produce url currentcontroller.mvc/23/ActionName/223 that is absolutely correct but when it loads the page it gives a JavaScript error in jquery1.4.2.min.js file.
This is strange: if I change id to someid =223 it will reflect in query string and there will be no JS error.
Edit: I have done some further debugging and found when both id and docid are mentioned in route values one thing is ignored in global.asax that is the ignore path.
routes.RouteExistingFiles = false;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.ignoreRoute is totally bypassed and I can see names of JS files in route value dictionary while debugging in my controller.
it gives javascript error in
jquery1.4.2.min.js file
The most likely cause for this is that something you are displaying on the page is different and you are performing an action that is causing the error. Can you supply enough of a sample from the rendered page to show what you are using jQuery for?
If we drag scripts from solution explorer to site.master it results in following output
<script type="text/javscript" src="../../scripts/jquery.min.js"></script>
The leading dots (..) are creating the problem. Putting source path in url.content or using /scripts instead of ../../scripts will solve the problem because these leading periods are forcing them to match some route in global.asax.

Resources