ASP.NET MVC 2 One Route Works, One Route Doesn't - asp.net-mvc

I have two routes in my ASP.NET MVC application.
The first is working fine - it's an ActionResult that returns a view.
The second is on the same controller and is an ActionResult that returns a Json response. It takes a couple of additional paramaters.
This second route is working on my dev machine, but when I deploy it to the server I get back a blank response. Any suggestions will be gratefully received.
I have also copy-pasted the route into a browser to eliminate any issues in the jQuery JavaScript.
The method
[HttpGet]
public ActionResult CheckSku(string id, string brand) {
CheckSkuModel model = new CheckSkuModel();
model.Id = id;
model.Brand = brand;
return Json(model, JsonRequestBehavior.AllowGet);
}
The routes
routes.MapRoute(
"Default", // Route name
"{controller}.mvc/{action}/{id}", // URL with parameters
new {
controller = "Orders", action = "Send", id = ""
} // Parameter defaults
);
routes.MapRoute(
"CheckSku", // Route name
"{controller}.mvc/{action}/{id}/{brand}", // URL with parameters
new {
controller = "Orders", action = "CheckSku", id = "", brand = ""
} // Parameter defaults
);

Two thing you can quickly check that may help:
1. Swap the two routes around so "CheckSku" is above "default"
2. Make the "CheckSku" more specific so will look something like:
routes.MapRoute(
"CheckSku", // Route name
"Orders.mvc/CheckSku/{id}/{brand}", // URL with parameters
new {
controller = "Orders", action = "CheckSku", id = "", brand = ""
} // Parameter defaults
);
that was another controller doesn't pick up the url by mistake.
An alternative is the use the routelink helper when generating the url so it points to the correct route.

When you say you "get back a blank response", do you mean you're not getting an error, but that the server isn't returning anything? What makes you think this is a routing issue?
Some troubleshooting tips:
Use Fiddler to examine the HTTP request you're making and the raw HTTP response the server is sending back. If you're getting a 500 response code then check the response for error information.
Can you attach a remote debugger to the server? This might give you a chance to investigate any exceptions that are raised.

Related

MVC Routing Parameter Precedence

I came across a scenario where I had the default MVC Route setup. Like So.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Then navigating to a url as such
domain/controller/action/1234
On this page I was then navigating to the same page but with different parameters after a certain event. Like so.
var id = $(this).data("id");
var url = "#Url.Action("action", "controller", new { area = ""})";
var params = $.param({id: id, vrnsearch: true});
var fullUrl = url += "?" + params;
window.location.href = fullUrl;
I noticed that the url was still keeping the same id in the url and attaching parameters like so.
domain/controller/action/1234?id=4321&vrnsearch=true
Now my question is, is there a way to determine a precedence over if it should use the value for id from the url or from the parameter.
I have actually found a work around/fix for my issue by using the below, which removes the id from the url and just uses parameters.
#Url.Action("action","controller", new {id = "", area = ""})
However was just curious if there is a precedence in parameters vs url routing.
The query string has nothing at all to do with routing (at least, not unless you customize routing to consider it).
The values that are passed to the ModelBinder and to your action method are done so by Value Providers. You can control the order of precedence by changing the order in which their corresponding ValueProviderFactory is registered in the static ValueProviderFactories.Factories property.
As you can see, the default configuration is to first use the RouteDataValueProviderFactory and if it returns no value it will try the QueryStringValueProviderFactory. If you change the order of the factories, the order of precedence changes.
ValueProviderFactories.Factories.RemoveAt(3);
ValueProviderFactories.Factories.Insert(4, new RouteDataValueProviderFactory());

Get url from MvcSiteMapProvider by key with parameter

I usually get the url from a node with the following code:
MvcSiteMapProvider.SiteMaps.Current.FindSiteMapNodeFromKey("AccountDetailsKey").Url
Now I have a node with a parameter. But how can I get the url for that node. So in the below example we need the url of the "AccountDetailsKey" node.
<mvcSiteMapNode key="BeherenAccountKey" title="Zoeken accounts" controller="BeherenAccount" action="BeherenAccount">
<mvcSiteMapNode key="AccountDetailsKey" title="Account details" controller="BeherenAccount" action="AccountDetails" preservedRouteParameters="gebruikersnaam" visibility="!SiteMapHelper,!MainMenu,*" />
</mvcSiteMapNode>
Details action:
[Route("account/details/{gebruikersnaam}")]
public ActionResult AccountDetails(string gebruikersnaam)
{
return this.View((object)gebruikersnaam);
}
De routeconfig:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapMvcAttributeRoutes();
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
Offcourse we could use the following for generating an url to the details page with regular MVC razor code:
#Url.Action("AccountDetails", "BeherenAccount", new { gebruikersnaam = User.Identity.Name.ToLower().Replace("domain\\", "") })
The thing is that we don't want to use action and controller names in our code. We want to generate all the urls from the sitemap. Everything works fine in the whole application but can't get this details page working. We don't have a DynamicNodeProvider because we don't care for separate titles, seo etc because it is an administrator application.
The application shows the loggedin user in the main menu (_Layout page) and this is an url to his own detail page.
So when the loggedin user has username "abc", the details url must be "account/details/abc".
When using preservedRouteParameters, the SiteMap does not automatically generate the route values that are supposed to be placed onto the node. They come from the current request of the page. Normally, when doing this you are expected to provide URLs using ActionLink, Action, RouteLink, or UrlHelper, as would typically be the case when doing CRUD operations, since the links would need to be derived from the database data.
#Html.ActionLink("Gebruikersnaam", "AccountDetails", "BeherenAccount", new { gebruikersnaam = "Value" }, null)
Alternatively, if no route value named gebruikersnaam exists in the current request, you can supply it manually.
string url;
var node = MvcSiteMapProvider.SiteMaps.Current.FindSiteMapNodeFromKey("AccountDetailsKey");
if (node != null)
{
node.RouteValues["gebruikersnaam"] = "Value";
url = node.Url;
}
When you set a route value outside of an ISiteMapNodeProvider or dynamic node provider, the value that is set will only last for the lifetime of the current request.
NOTE: I really don't understand the exact problem you are having with the above code. In my test project it is working fine regardless of what page you are on. If you want to investigate further, you can use the code from Controlling URL Behavior to mimic how the SiteMapNodeUrlResolver uses the MVC UrlHelper.

MVC routes.MapRoute name property

I'm brand new to MVC so please bear with me as I'm only on the second page of the MS Tutorial (see last code example). For the HelloWorldController the following MapRoute is added:
routes.MapRoute(
name: "Hello",
url: "{controller}/{action}/{name}/{id}");
I'm just wondering, is it purely the pattern matching that does the work and the name "Hello" is just for my own reference? If so, are there not naming conventions that should be followed saying the MapRoute should be called HelloWorldWelcome, where welcome is a method inside the HelloWorldController.cs (see above link). Or am i being pedantic?
The route name is also used by the UrlHelper class. For example:
var url = Url.Route("Hello", new
{
controller = "SomeController",
action = "SomeAction",
name = "charlie",
id = 123
});
This will generate a matching URL.
This feature is much more useful when you use Attribute Routing. For example, if on some controller you have an action:
[RoutePrefix("api/phonebook")]
public class PhonebookController
{
[HttpGet("contact/{id}", Name = "GetContact")]
public Contact GetContact(int id)
{
...
}
}
In other code you could use Url.Route("GetContact", new { id = 7 }) to generate the URL /api/phonebook/contact/7.
Please refer to details on ASP.NET MVC Routing Overview
Name attribute is for callign a route from your views or controller with route name.
From ActionLink your can use a routename:
Html.RouteLink("link_text", "route_name", route_parameters)
The question seems to be not so clearly answered (how the "Hello" route is choosen by the "HelloWorld" controller?), but as an Asp.Net MV5 begginer, I can see that the route is selected by default according to the match between the router url property and the URL parameters.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "ImageScan", action = "ScanImage", id = UrlParameter.Optional },
namespaces: new[] { "WebApplication3.Controllers" }
);
I am finding error :
Description: HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
Requested URL: /Views/ImageScan/ScanImage.cshtml

Default Routing Not working in .NET MVC 1 (and 2)

My default routes are very simple, but the page doesn't properly load without fully qualifying the entire route.
Here are the routes I'm using:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index" } // Parameter defaults
);
Here's the only action in the application in a HomeController:
public ActionResult Index()
{
return Content("New stuff");
}
With these URLs:
http://localhost:8081/NewMvc1/
I get The incoming request does not match any route.
With:
http://localhost:8081/NewMvc1/Home
http://localhost:8081/NewMvc1/Home/Index
I get a 404 Mvc page that says it tried to handle the request with a static file.
Yet, finally with a 'fully qualified url'
http://localhost:8081/NewMvc1/Home/Index/1
I get the expected result output from the one and only one action.
New Stuff
This doesn't seem right at all. I've also been getting Failed to Execute Action from this same application (not sure if that's related).
I've used Phil Haack's RouteDebugger to get this far, which pointed out that it wasn't matching the URL when the Optional parameters were missing, but did when those parameters were provided.
You're missing the id from your defaults:
new { controller = "Home", action = "Index", id = UrlParameter.Optional }

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