Rendering of #Ajax.ActionLink is messed up by adding a new route - asp.net-mvc-3

I have an ActionLink:
<td>
#Ajax.ActionLink(item.HostedBy, "_DetailsMerged", "Marcher",
new { id = item.HostedById },
new AjaxOptions
{
UpdateTargetId = "marcherId" + #i ,
HttpMethod="GET",
InsertionMode = InsertionMode.Replace,
})
</td>
that displays the appropriate link when I just have default routing. However, introducing a route for a geolocation proxy, (which implments IRouteHandler and is a custom route handler) BEFORE the default routing:
routes.Add("WebgisUscproxy", new Route("WebgisUscproxy", new OpenLayers_Bronze.Utility.WebgisUscProxyHandler()));
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
while working OK for semi-hard-coded links in my client javascript ajax call (that look like: /WebgisUscproxy?zip=10003), screws up how the #Ajax.ActionLink links are rendered. They ALSO pick up '/WebgisUscproxy'. So I get:
http://localhost:59723/WebgisUscproxy?action=_DetailsMerged&controller=Marcher&id=1
instead of:
http://localhost:59723/Marcher/_DetailsMerged/1
which is what I want, and get with just the default routing. Putting:
routes.Add("WebgisUscproxy", new Route("WebgisUscproxy", new OpenLayers_Bronze.Utility.WebgisUscProxyHandler()));
AFTER the default route handler also doesn't work, as the default routing now matches semi-hard-coded links, like '/WebgisUscproxy?zip=10003'.
==========================================================================
I've found a work-around, though I hope somebody posts something more direct.
routes.MapRoute("webgisusc", "WebgisUscProxy",
new { controller = "Utility", action = "WebgisUsc" }
).RouteHandler = new OpenLayers_Bronze.Utility.WebgisUscProxyHandler();
I had created an empty Utility controller, and was going to add a dummy "WebgisUscProxy"
action to it, but it turns out that there's no need for even a dummy UtilityController. This route definition works, all by itself.

Related

Html.BeginForm with dynamic routevalues

I need to add a dynamic routevalue in html.beginform, something like this
Html.BeginForm("action", "controller", new {
somethingID = "some js function or jquery that get the value from a textbox"
}))
I know mvc is already passing the paramenter to my method when the form submit, but I need the url to include the parameter in the mvc url format, ie mydomain.com/controller/action/somethingID. Eveything is working right now, but because I have another $.ajax() call that pass in the url, something like "../someMethod", the $.ajax() dont work because the current url is (mydomain.com/controller/action) not (mydomain.com/controller/action/somethingID).
Make sure to set as UrlParameter.Optional the id in your RouteConfig:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional}
);

Html.ActionLink equivalent of a specific URL format

I want to use Html.ActionLink to return an anchor tag with href like /Product/22/Product-Name, where Product is my controller name and 22 is my id and Product-Name is my title.
In my global.asax, I have set the following route :
routes.MapRoute(
"ProductRoute", // Route name
"Product/{id}/{title}", // URL with parameters
new { controller = "Product", action = "Index", id = UrlParameter.Optional });
I tried using following code
#Html.ActionLink(model.Name, null, "Product",
new { id = model.Id, title = model.Name.Replace(" ","-") }, null)
but it yields Product/Browse/22?title=Product-Name. This code is in Browse View returned by Browse action of Catalog controller and that's why it picks up the Browse in between.
Strangely, the same code works fine in the Index View returned by Index action of the Home Controller. What's the reason for this difference? . Am I missing something or this is a bug in Asp.net MVC3.
What Should I do to achieve my stated URL format. For the meantime, I am using this code
#product.Name
make sure you have defined the custom route before the default route and try
#Html.ActionLink(model.Name,
"Index",
new {controller="Product", id = model.Id, title = model.Name.Replace(" ","-") }, null)
the first parameter is the DisplayName, second the ActionResult's name and then the RouteValues

ASP.NET MVC 3 – How can I route directly to an action

I have a controller called HomeController with the actions Index(), MethodOne() and MethodTwo(). Each of these just return View() for now.
When I create an action link with the code:
#Html.ActionLink("Home", "Index", "Home")
I get the hyperlink:
Home
This is good however using the same ActionLink extention method to route too MethodOne I get the hyperlink:
MethodOne</li>
What do I need to configure so my site will accept the hyperlink “/MethodOne”, this currently returns a 404.
I have a suspicion this may be related to routing. My routing table is currently the default:
routes.MapRoute("Default", "{controller}/{action}/{id}",
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
});
You need a route like:
routes.MapRoute(
"MethodOne", //Your route name.
"methodone", //What your browser/user will see at the URL bar: localhost.com/methodone
new { controller = "Home", action = "MethodOne" } //What MVC3 will route to.
);
That will map and catch the request to the Home/MethodOne action method.

ASP.NET MVC 3 Controller route - make everything under home controller appear under the domain

Currently everything under homecontroller appears in the URL as
example.com/Home/{Action}
Is there a way we can keep all other routing the way it is but ONLY special case home controller so everything under home comes under the domain.
like
example.com/about
example.com/contact
example.com/error
instead of creating new controller classes for each of them.
EDIT:
The other URL's like
example.com/user/details/123
example.com/user/edit/123
Which are in the userController should work the same as they are now
I think the best way is:
routes.MapRoute("home", "home", new { controller = "Home", action = "Index" });
routes.MapRoute("about", "about", new { controller = "Home", action = "About" });
routes.MapRoute("contact", "contact", new { controller = "Home", action = "Contact" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
and when you want to create a link, use:
#Html.RouteLink("Home", "home", new{/* route values */}, new {/* html attribues */})
OR:
#Html.RouteLink("Home", "home")
instead of:
#Html.ActionLink("Home", "Index", "Home", new{/* route values */}, new {/* html attribues */})
this works for me, and should work for you too.
UPDATE:
you can create a symbol like # (or - or anything else), before the action part in url, to make the url unique, such as:
routes.MapRoute(
"test", // route name
"#{action}", // url and parameters
new {controller = "MyHome", action = "Home"} // parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
in this way, your urls are different from the Default map-route and you can create urls like:
site.com/#Home
site.com/#About
site.com/#Contact
but the first, in my idea, is better and I always use that.
Using the Attribute Routing of MVC5, I did similar to Javad_Amiry answer, by placing a route for each action in HomeController:
public class HomeController : Controller
{
[Route("about")]
public ActionResult About()
{
return View();
}
I think this is more maintainable than placing every action in the global RouteConfig.cs file. Better still to combine Attribute Routing with convention-based routing, so new actions added to controller will work by default without a Route attribute (eg: /Home/action) but can be improved by adding the Route attribute (eg: /action).
You could simply modify the default route and remove the controller bit from the url and specify that it will always be Home in the default values:
routes.MapRoute(
"Default",
"{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Obviously you realize that this limits your application to a single controller which is HomeController as now you no longer have any possibility to set it in your url. Stuffing all the actions in a single controller is a bad practice IMHO and violates a couple of principles like RESTful routing and SRP.
ASP.NET MVC root url’s with generic routing

LogOnPartial renders with a blank href - MVC 3

I'm using a standard MVC 3 Web Project and I've written my HTML out in a standard HTML file, and then copy/pasted it into the _layout.cshtml file. With all the correct RenderBody() and #Html.Partial("_LogOnPartial") included the page works fine, but the ActionLink inside the _LogOnPartial doesn't render an href.
Html.ActionLink("Log On", "LogOn", "Account")
Will come out as:
Log On
This is unchanged from the standard link that you get when you start an MVC 3 Web project.
The registered Routes are:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Products",
"{controller}/{action}/{id}",
new {controller = "Products", action = "Index"});
routes.MapRoute(
"Newsletter",
"{controller}/{action}/{emailAddress}",
new { controller = "Newsletter", action = "Index" });
routes.MapRoute(
"Account",
"{controller}/{action}/{id}",
new { controller = "Account", action = "LogOn", id = UrlParameter.Optional });
}
I don't understand why this is happening, but in Visual Studio it is not underlining the Action or Controller which makes me think it isn't seeing the AccountController properly. Anyone got any ideas?
Fabian is right. The problem is because there are too many routes, many of which are almost identical in their pattern. Your "Default", "Products" and "Account" routes all look for a controller, an action and an optional ID (either explicitly or implicitly). You would probably have considerably more success if you just set the default controller back to its factory-standard form like so:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new
{
controller = "Home",
action = "Index",
id = UrlParameter.Optional
}); // Parameter defaults
routes.MapRoute(
"Newsletter",
"{controller}/{action}/{emailAddress}",
new { controller = "Newsletter", action = "Index" });
}
Since the ID is optional, your Products routes will still be matched if you supply an ActionLink with no ID (e.g. #Html.ActionLink("My Link", "Products", "Index")) and the form of the "Account" route is identical to the "Default" one anyway. There's no need to use it and MVC is likely being tripped up between these, which is causing your LogOn partial's Href to fail.
ActionLink doesn't look at the controller or it's actions, just the routing table. Make sure you have a route with action "LogOn" and controller "Account" set in your global.asax.
Edit:
I recommend you read up a bit on mvc routing. Your current routes are too greedy and will match when they shouldn't.
For LogOn i would use something like this (put it at the top because its the least greedy since it doesnt contain any variables):
routes.MapRoute(
"Account",
"logon",
new { controller = "Account", action = "LogOn", id = UrlParameter.Optional });

Resources