I have created an Area named B2b
in my ASP.NET MVC application, and I have also created a sub-folder called Shopify
under this area:
In order to register the Shopify
sub-folder, I have created a CustomViewEngine
as below (followed this tutorial):
public class ExpandedViewEngine : RazorViewEngine
{
public ExpandedViewEngine()
{
var extendedViews = new[]
{
"~/Areas/B2b/Views/Shopify/{1}/{0}.cshtml",
};
var extendedPartialViews = new[]
{
"~/Areas/B2b/Views/Shopify/Shared/{0}.cshtml"
};
ViewLocationFormats = ViewLocationFormats.Union(extendedViews).ToArray();
PartialViewLocationFormats = PartialViewLocationFormats.Union(extendedPartialViews).ToArray();
}
}
And this is is my area registration code (I am using lowercase-dashed-route):
public class B2bAreaRegistration : AreaRegistration
{
public override string AreaName
{
get
{
return "B2b";
}
}
public override void RegisterArea(AreaRegistrationContext context)
{
// this route is for controllers and views inside Shopify sub-folder
var shopifyDefaultRoute = new LowercaseDashedRoute(
"B2b/Shopify/{controller}/{action}/{id}",
new RouteValueDictionary(new { controller = "ProductMap", action = "Display", id = UrlParameter.Optional }),
new DashedRouteHandler(),
this,
context,
new[] { "Shopless.Web.Areas.B2b.Controllers.Shopify" }
);
context.Routes.Add("Shopify_default", shopifyDefaultRoute);
// default area route which is not under Shopify subfolder
var b2bDefaultRoute = new LowercaseDashedRoute(
"B2b/{controller}/{action}/{id}",
new RouteValueDictionary(new { action = "index", id = UrlParameter.Optional }),
new DashedRouteHandler(),
this,
context,
new[] { "Shopless.Web.Areas.B2b.Controllers" }
);
context.Routes.Add("B2b_default", b2bDefaultRoute);
}
}
And I register the above in Global.asax:
protected void Application_Start()
{
ViewEngines.Engines.Add(new ExpandedViewEngine());
AreaRegistration.RegisterAllAreas();
// more code ...
}
Everything works fine, except the following code:
@using (Html.BeginForm("update", "organisation", new { area = "B2b" }, FormMethod.Post))
{
<input type="text" id="name" name="name">
}
Is generating the following HTML:
<form action="/b2b/shopify/organisation/update" method="post" novalidate="novalidate">
<input type="text" id="name" name="name">
</form>
Notice that it is adding shopify
after my area name, B2b
. The above form is inside B2b
area but it is not under shopify
subfolder, so not sure why it is being added?
It is mapping to this route template "B2b/Shopify/{controller}/{action}/{id}"
because it also matches the conventional values given to the BeginForm
when generating the URL for the form.
Both of the area route conventions conflict with each other for URL generation.
If I ask the route table to generate a URL and I give it a controller, action, and area. Which route would match first given the following route templates within the same area
B2b/Shopify/{controller}/{action}/{id}
B2b/{controller}/{action}/{id}
And since first match always win, it will map to the first one above, which would explain the current experience with your form.
If you want to use a specific route to generate your URL for the Form use BeginRouteForm
Method
@using (Html.BeginRouteForm(
routeName: "B2b_default",
routeValues: new { action = "update", controller = "organisation", area = "B2b" },
method: FormMethod.Post)
)
{
<input type="text" id="name" name="name">
}