Url.Action生成查询而不是参数URL

时间:2017-01-23 20:46:20

标签: asp.net-mvc attributerouting

这是控制器类。我只显示方法签名。

[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);
}

问题在于调用

@Url.Action("index", "specifications", new RouteValueDictionary() { { "subcategoryID", @subcategory.SubcategoryID } })

返回

  

/规格?subcategoryID = 15

而不是

  

/规格/ 15

为什么会这样?我没有任何类似的方法在这条路线上期待这个!

2 个答案:

答案 0 :(得分:3)

您生成网址的电话不正确。要匹配控制器名称,它应该是“规范”而不是“规范”。

@Url.Action("index", "specification", new { subcategoryID=subcategory.SubcategoryID })

请注意,[Route]属性中指定的网址只是装饰性的。您的路由值必须与控制器名称和操作方法名称匹配,才能利用该路由生成URL。

为了让那些维护代码的人更清楚(并且稍微快一些),最好使参数值Pascal大小写就像控制器和动作名一样。

@Url.Action("Index", "Specification", new { subcategoryID=subcategory.SubcategoryID })
  

为什么会这样?

-------------------------------------------------------------
| Route Key          | Route Value   | Your Action Request  |
|--------------------|---------------|----------------------|
| Controller         | Specification | Specifications       | No Match
| Action             | Index         | Index                | Match
| subcategoryID      | ?             | XXX                  | Match (Always)
-------------------------------------------------------------

要获得路由匹配,@Url.Action的所有参数必须与路由值字典匹配。问题是路由值字典中未定义Controller=Specifications,因为 实际控制器名称 SpecificationController。因此,无论您在Specification属性中放置什么,路由值名称都为[Route]。 URL ~/specifications/{subcategoryID?}与传出(URL生成)匹配完全没有任何关系 - 它只匹配传入的URL并确定URL生成时的外观。

如果要使用Specifications而不是Specification作为路由值,则需要将操作方法​​移动到名为SpecificationsController的新控制器。也就是说,我看不出它有什么不同,因为无论如何最终用户都不会看到路由值名称。

答案 1 :(得分:0)

您必须使用此功能才能生成以下网址:/specifications/15

@Url.Action("index", "specifications", new { subcategoryID=subcategory.SubcategoryID })

[Route("~/specifications/{subcategoryID?}")]
public ActionResult Index(int? subcategoryID);
  

我做错了什么以及如何恢复使用subategoryID作为   参数名称?

您必须添加另一条路线(在DEFAULT ROUTE之前)才能拥有另一个optional参数:

这样的事情:

 routes.MapRoute(
         "SecondRoute",
         "{controller}/{action}/{subcategoryID}",
          defaults: new { controller = "Home", action = "Index", subcategoryID = UrlParameter.Optional }
 );