How do I setup default routes that match just parameters? - asp.net-mvc

This is how I want my routes to work:
http://example.com -> UpdatesController.Query()
http://example.com/myapp/1.0.0.0 -> UpdatesController.Fetch("myapp", "1.0.0.0")
http://example.com/myapp/1.0.0.1 -> UpdatesController.Fetch("myapp", "1.0.0.1")
http://example.com/other/2.0.0.0 -> UpdatesController.Fetch("other", "2.0.0.0")
My controller looks like this:
public class UpdatesController : Controller {
public ActionResult Query() { ... }
public ActionResult Fetch(string name, string version) { ... }
}
The route config that I've tried is this:
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Fetch",
url: "{name}/{version}",
defaults: new { controller = "Updates", action = "Fetch" },
constraints: new { name = #"^.+$", version = #"^\d+(?:\.\d+){1,3}$" }
);
routes.MapRoute(
name: "Query",
url: "",
defaults: new { controller = "Updates", action = "Query" }
);
But only the first example works. The others that should call the Fetch action method all fail with 404.
What am I doing wrong?
(I've also tried it without the route constraints, but there is no difference)

add following code to web.config, because your url contains dot value (1.0.0.0)
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
Another way
you can do it via Attribute routing.
to enable attribute routing, write below code in RouteConfig.cs
routes.MapMvcAttributeRoutes();
In controller your Action look like this
[Route("")]
public ActionResult Query()
{
return View();
}
[Route("{name}/{version}")]
public ActionResult Fetch(string name, string version)
{
return View();
}

Related

Custom route that match a single specific url

In my mvc app, I want to dynamically generate a specific url :
https://myapp.corp.com/.well-known/microsoft-identity-association.json
This endpoint should produce a small file based on values in the web.config file. So I created this controller :
public class HostingController : Controller
{
// GET: Hosting
[OutputCache(Duration = 100, VaryByParam = "none")]
public ActionResult MicrosoftIdentityAssociation() => Json(new
{
associatedApplications = new[]
{
new { applicationId = WebConfigurationManager.AppSettings.Get("ClientId") }
}
});
}
And I changed the routing configuration like this :
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Azure domain registration",
".well-known/microsoft-identity-association.json",
new { controller = "Hosting", action= "MicrosoftIdentityAssociation" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
I expect the url to produce json like :
{
"associatedApplications": [
{
"applicationId": "1562019d-44f7-4a9d-9833-64333f52181d"
}
]
}
But when I target the url, I got a 404 error.
What's wrong ? how to fix ?
You can use a route attribute:
[Route("~/.well-known/microsoft-identity-association.json")]
[OutputCache(Duration = 100, VaryByParam = "none")]
public ActionResult MicrosoftIdentityAssociation()
{
..... your code
}
It was tested in postman.
Asp.Net MVC can't create route that have extension. I had to edit my Web.config to plug the MVC framework on this very specific file.
Specifically :
<system.webServer>
<handlers>
<add name="Azure domain verifier"
path=".well-known/microsoft-identity-association.json"
verb="GET" type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0"
/>
</handlers>
</system.webServer>
From this point, I was able to route to my custom controller action using either routeconfig.cs file or the [RouteAttribute]

Same route parameters with different controllers' action methods causes an error in Asp .Net MVC

I m using attribute routing feature of Asp .Net Mvc.
My first action is like below which is placed in SurveyController
[Route("{surveyName}")]
public ActionResult SurveyIndex()
{
return View();
}
And my second action is like below which is placed in MainCategoryController
[Route("{categoryUrlKey}")]
public ActionResult Index(string categoryUrlKey)
{
return View();
}
I'm not using convention based routing.
Below is my RouteConfig.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
routes.MapAttributeRoutes();
}
Now the problem is when i click to a survey it redirects to the MainCategory/Index route. I know it is because of same route pattern but i cant change this into another thing.
how can I handle this situation?
Thanks
You should prefix the routes on your MainCaregoryController, either at the controller level like this:
[RoutePrefix("category")]
public class MainCategoryController : Controller {
or at the action level like this:
[Route("category/{categoryUrlKey}")]
public ActionResult Index(string categoryUrlKey)
{
return View();
}
Routes should not clash. This route:
[Route("{categoryUrlKey}")]
public ActionResult Index(string categoryUrlKey)
{
return View();
}
matches any string and passes that string value into the action, so without a prefix it will match:
http://localhost/validcategorykey
and
http://localhost/something/id/isthispointmakingsense
and your categoryUrlKey parameter would equal "validcategorykey" in the first instance and "something/id/isthispointmakingsense" in the second.
Now as for this route:
[Route("{surveyName}")]
public ActionResult SurveyIndex()
{
return View();
}
This just won't work period. This needs to be changed to:
[Route("survey/{surveyName}")]
public ActionResult SurveyIndex(string surveyName)
{
return View();
}

MVC5 Url.Action not returning correct URL

I'm trying to use a Kendo Grid for a list of objects on my model, but the url's generated by the .Create() etc. methods are not generating the url correctly.
It doesn't appear to be just Kendo though because even in my controller using Url.Action() generates the wrong url.
// POST: Assessment/Create
[HttpPost]
[ValidateAntiForgeryToken]
[Route("eForms/Assessment/Create")] // <-- Tried with and without this
public ActionResult Create(AssessmentPoco model)
{
var x = Url.Action(("Allergy_Read", "Assessment");
}
//POST: Assessment/Allergy_Read
[HttpPost, ActionName("Allergy_Read")]
[Route("AllergyRead", Name = "Allergy_Read")]
public ActionResult Allergy_Read([DataSourceRequest] DataSourceRequest request, AssessmentAllergiesSection model) //, int id)
{
return Json(new[] { model }.ToDataSourceResult(request, ModelState));
}
Expected: eForms/Assessment/Allergy_Read
Actual: /?action=Allergy_Read&controller=Assessment
Route config:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("");
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//web forms default
routes.MapPageRoute(
routeName: "WebFormDefault",
routeUrl: "",
physicalFile:"~/default.aspx");
routes.MapRoute(
name: "API",
url: "eforms/api/{controller}/{action}/{id}",
defaults: new {controller="Customer", action="GetCustomers", id = UrlParameter.Optional}
);
////mvc default
routes.MapRoute(
name: "Default",
url: "eforms/{controller}/{action}/{id}",
defaults: new { controller = "IncidentReports", action = "Search", id = UrlParameter.Optional }
);
}
Not sure what else could be at fault here (besides my brain), any ideas?
Clarifications (from comments):
We are using Areas
Global.asax is calling RegisterRoutes (also tried turning it off no change)
Update:
This project is a newly added MVC project to an existing ASP.Net WebForms app. I updated the Route config because I was using looking at the wrong one.
You're using routeAttribute, so put a name inside it and use Html.RouteLink or Url.RouteUrl instead of Url.Action().
Example:
[Route("menu", Name = "mainmenu")]
public ActionResult MainMenu() { ... }
Usage in View:
Main menu
I tried this code in controller:
public class HomeController : Controller
{
[Route("AllergyRead", Name = "Allergy_Read")]
public ActionResult Allergy_Read()
{
return View();
}
}
And:
#Html.RouteLink("Allergy Read", "Allergy_Read")
Give me the right route to action. I can't figure out why your implementation isn't working.

Right way to Redirect a URL segment to MVC Controller

I have an existing Controller
public class HomeController : Controller
{
public ActionResult Index()
{
return Redirect("/Scorecard");
}
[OutputCache(Duration = 18000)]
public ActionResult Scorecard()
{
return View();
}
}
This currently Maps to http://siteurl/Home/Scorecard . I wanted to the segment http://siteurl/scorecard to redirect to this Controller Action . What would the best wayt to do this . I tried checking the RequestUrl in Session_Start in Global.aspx but the redirects dont seem to be happening . The other alternative I thought of was using a Different Controller like "ScorecardController" and then having a RedirectToAction("Scorecard","Home") in the Index view there.
you could add a FilterAccess class on your App_Start folder to do something like this:
public class FilterAcess : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
//Redirect
if (HttpContext.Current.Request.Url=="http://siteurl/scorecard"){
context.HttpContext.Response.Redirect("~/Home/Scorecard");
}
}
}
RedirectToAction is better way to do it, because, in case you change routing table later, redirect URL will be in adapted.
public class HomeController: Controller
{
public ActionResult Index()
{
return RedirectToAction("Scorecard");
}
[OutputCache(Duration = 18000)]
public ActionResult Scorecard()
{
return View();
}
}
You should also update RouteTable with additional route, before "Default" route:
public static void RegisterRoutes(RouteCollection routes)
{
routes.LowercaseUrls = true;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "NoHomeSegmentInUrl",
url: "{action}/{id}",
defaults: new { controller = "Home", id = UrlParameter.Optional });
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
And, for lower case routes you need line routes.LowercaseUrls = true;

Asp.Net MVC 4 routing and link generation

In ASP.NET MVC 4 I wonder about the behavior, how links are generated for me.
Imagine a simple controller with 3 actions, each taking an integer parameter "requestId", for example:
public class HomeController : Controller
{
public ActionResult Index(int requestId)
{
return View();
}
public ActionResult About(int requestId)
{
return View();
}
public ActionResult Contact(int requestId)
{
return View();
}
}
and this registered route (before the default route):
routes.MapRoute(
name: "Testroute",
url: "home/{action}/{requestId}",
defaults: new { controller = "Home", action = "Index" }
);
I call my index-view using http://localhost:123/home/index/8
On this view, I render links for the other two actions:
#Html.ActionLink("LinkText1", "About")
#Html.ActionLink("LinkText2", "Contact")
Now I expect MVC to render this links including the current route-value for "requestId", like this:
http://localhost:123/home/about/8
http://localhost:123/home/contact/8
But i get these links (without the paramter):
http://localhost:123/home/about
http://localhost:123/home/contact
...but not for the index-action if i would specify one:
#Html.ActionLink("LinkText3", "Index")
What I want to avoid is to explicitly specify the parameters in this manner:
#Html.ActionLink("LinkText1", "Contact", new { requestId = ViewContext.RouteData.Values["requestId"] })
When I move the requestId parameter before the action paramter it works like I expect it, but I don't want to move it:
routes.MapRoute(
name: "Testroute",
url: "home/{requestId}/{action}",
defaults: new { controller = "Home", action = "Index" }
);
Can someone explain me this behavior? How can I get this to work without specifying the parameter explicitly?
InController:
Replace the int to nullable int
For Routing:
set requestId as optional in routing
routes.MapRoute(
name: "Testroute",
url: "home/{action}/{requestId}",
defaults: new { controller = "Home", action = "Index" ,requestId=RouteParameter.Optional }
);

Resources