ASP.NET MVC URL Routing with ControllerName/ExampleID - asp.net

i'm getting this error when i'm navigate browser to url:
localhost:10793/RealEstates/10
this my RouteConfig code:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Main", action = "Index" }
);
routes.MapRoute(
name: "RealEstates",
url: "RealEstates/{action}",
defaults: new { controller = "RealEstates", action = "Index" }
);
routes.MapRoute(
name: "RealEstatesViewAd",
url: "RealEstates/{id}",
defaults: new { controller = "RealEstates", action = "ViewAd", id = UrlParameter.Optional }
);
}
}
my 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.
when changed code to:
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//routes.MapRoute(
// name: "Default",
// url: "{controller}/{action}",
// defaults: new { controller = "Main", action = "Index" }
//);
//routes.MapRoute(
// name: "RealEstates",
// url: "RealEstates/{action}",
// defaults: new { controller = "RealEstates", action = "Index" }
//);
routes.MapRoute(
name: "RealEstatesViewAd",
url: "RealEstates/{id}",
defaults: new { controller = "RealEstates", action = "ViewAd", id = UrlParameter.Optional }
);
}
}
it's work but when i call on other actions in controller
localhost:10793/RealEstates/CreateAd
this error found
The parameters dictionary contains a null entry for parameter 'id' of
non-nullable type 'System.Int32' for method
'System.Web.Mvc.ActionResult ViewAd(Int32)' in
'Youe3lan.Controllers.RealEstatesController'. An optional parameter
must be a reference type, a nullable type, or be declared as an
optional parameter.
Parameter name: parameters
and this my controller:
namespace MvcAppliction1.Controllers
{
public class RealEstatesController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult ViewAd(int id)
{
return View();
}
public ActionResult CreateAd()
{
return View();
}
}
}

You need to change it to:
routes.MapRoute(
name: "RealEstatesViewAd",
url: "RealEstates/{action}/{id}",
defaults: new { controller = "RealEstates", action = "ViewAd", id UrlParameter.Optional }
);}}
Have a look here it might help:
http://msdn.microsoft.com/en-us/library/cc668201(v=vs.100).aspx
UPDATE
Add this to your controller:
public ActionResult ViewAd(Int32 id)
{
return View();
}
You see
localhost:10793/RealEstates/10
is translated to:
localhost:10793/RealEstates/ViewAdd/10
So you need that method in the controller accepting an it parameter.

you've flagged your id in your route as optional:
id = UrlParameter.Optional
but I bet your controller isn't nullable??
public ActionResult ViewAd(Int32 id)
{
}
So you cant post a null into your id even though the route allows it. If you change this to:
public ActionResult ViewAd(Int32? id)
{
}
You won't get the error message:
The parameters dictionary contains a null entry for parameter 'id' of
non-nullable type 'System.Int32' for method
'System.Web.Mvc.ActionResult ViewAd(Int32)' in
'Youe3lan.Controllers.RealEstatesController'. An optional parameter
must be a reference type, a nullable type, or be declared as an
optional parameter. Parameter name: parameters

Related

Having issues generating URLs for custom routes to include the users culture in the RouteValues

I'm trying to create a custom route which will include the users culture in the route (RouteValues). Using default routing convention everything works fine.
I have the following controller:
public class HomeController : Controller
{
public HomeController()
{
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
}
I believe I've configured localization in the app correctly as follows:
public void ConfigureServices(IServiceCollection services)
{
services.Configure<RequestLocalizationOptions>(opts =>
{
opts.SupportedCultures = new[] { new CultureInfo("en"), new CultureInfo("fr") };
opts.SupportedUICultures = opts.SupportedCultures;
opts.SetDefaultCulture("en");
opts.DefaultRequestCulture = new RequestCulture("en");
opts.RequestCultureProviders.Insert(0, new RouteDataRequestCultureProvider);
opts.ApplyCurrentCultureToResponseHeaders = opts.ApplyCurrentCultureToResponseHeaders;
});
services.AddControllersWithViews(opts =>
{
opts.Filters.Add(new CultureFilter("en"));
});
services.AddLocalization();
services.AddMvc();
}
And I have an ActionFilter that sets the users culture based on the route value.
public class CultureFilter : IAuthorizationFilter
{
private readonly string defaultCulture;
public CultureFilter(string defaultCulture)
{
this.defaultCulture = defaultCulture;
}
public void OnAuthorization(AuthorizationFilterContext context)
{
var values = context.RouteData.Values;
string culture = (string)values["culture"] ?? this.defaultCulture;
CultureInfo ci = new CultureInfo(culture);
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(ci.Name);
}
}
Using the default routing convention I get the desired result (more or less).
Thus for the following routes:
endpoints.MapControllerRoute(
name: "culture-default",
pattern: "{culture=en}/{controller=Home}/{action=Index}");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}");
Thus while on the url "http://localhost" I get:
"#Url.ActionLink("Index", "Home")" = "http://localhost"
"#Url.ActionLink("Privacy", "Home")" = "http://localhost/home/privacy"
And while on the url "http://localhost/fr" I get:
"#Url.ActionLink("Index", "Home")" = "http://localhost/fr"
"#Url.ActionLink("Privacy", "Home")" = "http://localhost/fr/home/privacy"
Ok - so far so goood....
But when I add a custom route for the Privacy ActionMethod I can't seem to get the correct culture in the generated URL.
Thus for the following routes:
endpoints.MapControllerRoute(
name: "culture-privacy",
pattern: "{culture}/h/p",
defaults: new { culture = "en", controller = "Home", action = "Privacy" });
endpoints.MapControllerRoute(
name: "default-privacy",
pattern: "h/p",
defaults: new { controller = "Home", action = "Privacy" });
Thus while on the url "//localhost" I get:
"#Url.ActionLink("Index", "Home")" = "//localhost"
"#Url.ActionLink("Privacy", "Home")" = "//localhost/h/p"
And while on the url "//localhost/fr" I get:
"#Url.ActionLink("Index", "Home")" = "//localhost/fr"
"#Url.ActionLink("Privacy", "Home")" = "//localhost/en/h/p"
Presumably this is because I included the "culture = 'en'" in the default for the "culture-privacy" route, but shouldn't the default value of 'en' only be used if the culture is not otherwise specified in the route?
You are right, the reason is that the default value "en" is overriding the value passed in the route data. If you want to use the culture which user typed, try to use the culture value passed in the route data instead of a fixed value. Here is the code sample:
endpoints.MapControllerRoute(
name: "culture-privacy",
pattern: "{culture}/h/p",
defaults: new { culture = "{culture}", controller = "Home", action = "Privacy" });

Route Confusion with Single Action

I am clearly having issue understanding the routes here or trying to achieve which is not possible.
I have this in my RouteConfig:
routes.MapRoute(
name: "Explorer",
url: "{controller}/{action}/{prefix}/{value}",
defaults: new { controller = "Explorer", action = "Index", prefix ="", value = UrlParameter.Optional }
);
And in Explorer Controller I have the following:
[RoutePrefix("Explorer")]
public class ExplorerController : Controller
{
public ActionResult Index()
{
return View();
}
[Route("id/{value}")]
public ActionResult Import(decimal? importId)
{
return View();
}
[Route("text/{value}")]
public ActionResult Import(string importWindow)
{
return View();
}
}
One of the ACTION (Import) has different PREFIX such as window and id but whenever I try to access it (such as https://localhost/Explorer/Import/window/helloWorld OR https://localhost/Explorer/Import/id/200) it keeps giving me the following error
The current request for action 'Import' on controller type
'ExplorerController' is ambiguous between the following action
methods: System.Web.Mvc.ActionResult
Import(System.Nullable`1[System.Decimal]) on type
projectname.Controllers.ExplorerController System.Web.Mvc.ActionResult
Import(System.String) on type projectname.Controllers.ExplorerController
I know it is ambiguous but I have a prefix which should make it non-ambiguous.
What am I doing wrong here and how to achieve this outcome if this is not the right way to do it?
Apply the [Route()] attribute for action methods in the controller class:
[RoutePrefix("Explorer")]
public class ExplorerController : Controller
{
// GET: Explorer
public ActionResult Index()
{
return View();
}
// Example: https://localhost/Explorer/Import/id/200
[Route("Import/id/{importId:decimal}")]
public ActionResult Import(decimal? importId)
{
return View();
}
// Example: https://localhost/Explorer/Import/window/helloWorld
[Route("Import/{text}/{importWindow}")]
public ActionResult Import(string importWindow)
{
return View();
}
}
Define only the Default route in the RegisterRoutes() method:
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 }
);
}

Url.Action() does not use good route config

I have overridden a default route in my routes configuration :
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.MapRoute("MyController_OverriddenAction",
"MyController/OverriddenAction",
new { controller = "MyOverriddenController", action = "OverridenAction" },
new[] { "Plugin" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "home", action = "Index", id = UrlParameter.Optional }
);
}
}
If I call MyController/OverriddenAction, the overridden action OverriddenAction in MyOverriddenController is displayed. It works.
But if I call #Html.Action("OverriddenAction", "MyController"), the default route is called.
Why? What is the solution?
My controllers :
public class MyOverridenController : Controller
{
public ActionResult OverriddenAction()
{
return Content("overridden");
}
}
public class MyController : Controller
{
public ActionResult OverriddenAction()
{
return new EmptyResult();
}
[...]
}
You should use following syntax
#Html.Action("OverriddenAction", "MyOverriden")
while calling the method directly like MyController/OverriddenAction it looks for the entry in MapRoute. However, while using #Html.Action you should use the actual controller name.

MVC4 Default Route to point to an area

I have 2 areas in my project:
Areas | Admin
Areas | FrontEnd
What I would like is when I visit the site, the default route should load Controllers / Views / Models from the FrontEnd area. It's normal to have Url/Admin for an admin panel but I would rather not have to force Url/FrontEnd (or some other variation). Basically I don't want to use the Controller / Model / View folders on the root level.
I'm not sure how to change the code to allow this or even it's an advisable method. Could someone provide some guidance please?
What I have:
routes.MapRoute(
"Admin_default",
"Admin/{controller}/{action}/{id}",
new {
area = "Admin",
controller = "Home",
action = "Index",
id = UrlParameter.Optional
},
namespaces: new[] { "WebsiteEngine.Areas.Admin.Controllers" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new {
area = "FrontEnd",
controller = "Home",
action = "Index",
id = UrlParameter.Optional
},
namespaces: new[] { "WebsiteEngine.Areas.FrontEnd.Controllers" }
);
However this produces an error:
The view 'Index' or its master was not found or no view engine supports the searched locations. The following locations were searched:
~/Views/Home/Index.aspx
~/Views/Home/Index.ascx
~/Views/Shared/Index.aspx
~/Views/Shared/Index.ascx
~/Views/Home/Index.cshtml
~/Views/Home/Index.vbhtml
~/Views/Shared/Index.cshtml
~/Views/Shared/Index.vbhtml
I do have views available in the areas and this doesn't look like it's looking there.
I believe you can just do something like this:
// Areas/Admin/AdminAreaRegistration.cs
public class AdminAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "Admin"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "Admin_Default",
url: "Admin/{controller}/{action}/{id}",
defaults: new
{
area = "Admin",
controller = "Home",
action = "Index",
id = UrlParameter.Optional
});
}
}
// Areas/Admin/FrontEndAreaRegistration.cs
public class FrontEndAreaRegistration : AreaRegistration
{
public override string AreaName
{
get { return "FrontEnd"; }
}
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
name: "FrontEnd_Default",
url: "{controller}/{action}/{id}",
defaults: new
{
area = "FrontEnd",
controller = "Home",
action = "Index",
id = UrlParameter.Optional
});
}
}
// Global.asax.cs
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
...
}
Now, in your RouteConfig class, you probably have a Default route set up. Bear in mind that as long as you call AreaRegistration.RegisterAllAreas before you call RouteConfig.RegisterRoutes, the routes that you set up in the areas may override the routes you set up in RouteConfig. (Routes are evaluated in the order they appear in the Routes collection, and .MapRoute pushes new routes to the end)

asp.net mvc routing id parameter

I am working on a website in asp.net mvc. I have a route
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
// Parameter defaults
);
which is the default route. And I have a method
public ActionResult ErrorPage(int errorno)
{
return View();
}
Now if I want to run this code with http://something/mycontroller/Errorpage/1
it doesn't work. But if I change the parameter name to id from errorno
it works.
Is it compulsory to have same parameter name for this method? Or do I need to create separate routes for such situations?
So, you have a parameter named errorno, and you want it to have a value from parameter id. This is obviously the binding problem.
How to solve it:
create a class for model binder:
public class ParameterBinder : IModelBinder
{
public string ActualParameter { get; private set; }
public ParameterBinder(string actualParameter)
{
this.ActualParameter = actualParameter;
}
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
object id = controllerContext.RouteData.Values[this.ActualParameter];
return id;
}
}
create a custom attribute for custom model binding:
[AttributeUsage(AttributeTargets.Parameter)]
public class BindParameterAttribute : CustomModelBinderAttribute
{
public string ActualParameter { get; private set; }
public BindParameterAttribute(string actualParameter)
{
this.ActualParameter = actualParameter;
}
public override IModelBinder GetBinder()
{
return new ParameterBinder(this.ActualParameter);
}
}
apply the new attribute to your action parameters as needed:
public ActionResult ErrorPage(
[BindParameter("id")]
int errorno)
{
return View();
}
Now your errorno will have the value, which was passed as id for your url.
Note: you can remove the paramter id from the example above, if you are sure you need it solved only for id.
Leaving this way will allow you bind other parameters too.
Option 1
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
public ActionResult ErrorPage(int id)
{
return View();
}
Option 2
routes.MapRoute(
"Default",
"{controller}/{action}/{errorno}",
new { controller = "Home", action = "Index", errorno = UrlParameter.Optional }
);
public ActionResult ErrorPage(int errorno)
{
return View();
}
Option 3
routes.MapRoute(
"Default",
"{controller}/{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
public ActionResult ErrorPage(int id)
{
int errorno = id;
return View();
}
use the bind attribute prefix:
public ActionResult Customer([Bind(Prefix = "id")]string cname) {}
#Parminder
The default route can handle all action with one parameter "id". And I think not every action need this parameter. So I change my default route
routes.MapRoute(
"Default",
"{controller}/{action}",
new { controller = "Home", action = "Index"}
);
and you can add a new route:
routes.MapRoute("errorpage", "yourcontroller/errorpage/{errorno}",
new {controller="controllername", action="errorpage"});
this just handle your controll name is "controllername". If you want to handle all controller, you can add this:
routes.MapRoute("errorpage", "{controller}/errorpage/{errorno}",
new {controller="controllername", action="errorpage"});
This method will create very much code in global.asax if you need a lot of custom route.
You could either rename the parameter in the default root (which probably is not a good idea) or rename it in the action method. Adding another root will not help because it will be the same as the default one and given an url the routing engine cannot distinguish between the two and will always take the first one in the list.
try to use the same name of parameter in action method as in in the route table url parameter.
global.asx
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
myController
public ActionResult ErrorPage(int id)
{
return View();
}

Resources