This is the controller class. I am showing only method signatures.
[Authorize]
[RoutePrefix("specification")]
[Route("{action=index}")]
public class SpecificationController : BaseController
{
[HttpGet]
[Route("~/specifications/{subcategoryID?}")]
public ActionResult Index(int? subcategoryID);
[HttpPost]
[Route("get/{subcategoryID?}")]
public JsonResult Get(int? subcategoryID);
[HttpGet]
[Route("~/specifications/reorder/{subcategoryID}")]
public ActionResult Reorder(int subcategoryID);
[HttpGet]
[Route("new/{id?}")]
public ActionResult New(int? id);
[HttpGet]
[Route("edit/{id?}")]
public ActionResult Edit(int id);
[HttpPost]
[ValidateAntiForgeryToken]
[Route("edit")]
public JsonResult Edit(SpecificationJson specification);
[HttpPost]
[Route("moveup")]
public JsonResult MoveUp(int specificationID);
[HttpPost]
[Route("movedown")]
public JsonResult MoveDown(int specificationID);
[HttpDelete]
[Route]
public ActionResult Delete(int id);
}
The problem is that calling
@Url.Action("index", "specifications", new RouteValueDictionary() { { "subcategoryID", @subcategory.SubcategoryID } })
returns
/specifications?subcategoryID=15
instead of
/specifications/15
Why is this happening? I do not have any similar methods on that route expect this one!
Your call to generate the URL is incorrect. To match the controller name, it should be "specification" not "specifications".
@Url.Action("index", "specification", new { subcategoryID=subcategory.SubcategoryID })
Keep in mind, the URL specified in the [Route]
attribute is only cosmetic. Your route values must match the controller name and action method name for it to utilize that route to generate the URL.
To make this more clear for those maintaining the code (and slightly faster), it might be better to make the parameter values Pascal case just like the controller and action names.
@Url.Action("Index", "Specification", new { subcategoryID=subcategory.SubcategoryID })
Why is this happening?
-------------------------------------------------------------
| Route Key | Route Value | Your Action Request |
|--------------------|---------------|----------------------|
| Controller | Specification | Specifications | No Match
| Action | Index | Index | Match
| subcategoryID | ? | XXX | Match (Always)
-------------------------------------------------------------
To get a route match, all parameters of @Url.Action
must match the route value dictionary. The problem is that Controller=Specifications
is not defined in the route value dictionary because your actual controller's name is SpecificationController
. Therefore, the route value name is Specification
regardless of what you put in the [Route]
attribute. The URL ~/specifications/{subcategoryID?}
has nothing at all to do with an outgoing (URL generation) match - it only matches incoming URLs and determines what the URL will look like when it is generated.
If you want to use Specifications
instead of Specification
for the route value, you need to move the action method to a new controller named SpecificationsController
. That said, I don't see what difference it makes, since the end user won't see the route value name anyway.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With