2017-01-23 26 views
2

這是控制器類。我只顯示方法簽名。Url.Action生成查詢而不是參數URL

[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

你調用生成的URL是不正確。要匹配控制器名稱,它應該是「規格」而不是「規格」。

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

請注意,在[Route]屬性中指定的URL只是表面化的。您的路由值必須與控制器名稱和操作方法名稱匹配,才能使用該路由生成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。因此,無論您在[Route]屬性中放置什麼,路由值名稱都是Specification。URL ~/specifications/{subcategoryID?}與傳出(URL生成)匹配完全沒有關係 - 它只匹配傳入的URL並確定URL在生成時的外觀。

如果要爲路由值使用Specifications而不是Specification,則需要將操作方法​​移至名爲SpecificationsController的新控制器。也就是說,我看不出它有什麼不同,因爲最終用戶無論如何都不會看到路由值名稱。

+0

我知道,如果我按照你說的那樣做,它就會起作用。之前就是這樣。爲了更加一致,我決定,當我返回所有結果時,它應該說/規範而不是/規範,因爲後者意味着它只是我們正在討論的一個規範。此外,我認爲通過在路由屬性中使用〜/ specifications,我明確表示我正在重新啓動路由,而不是使用控制器中指定的路由前綴。 – Rob

+1

是的,但爲了使其工作,您必須將操作方法​​移至名爲'SpecificationsController'的控制器。通過沒有正確指定它,你會得到一個路由未命中並且它與另一條路由相匹配,這就是爲什麼你正在查詢字符串。 – NightOwl888

+0

這工作就像一個魅力。我認爲改寫路線會完全重新編寫它。看起來你是對的! – Rob

0

你必須使用這種以產生如下網址:/specifications/15

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

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

我做了什麼錯,我怎麼能恢復使用subcategoryID作爲 參數的名字嗎?

您必須添加另一條路線(默認路由之前),以便有另一個optional參數:

事情是這樣的:

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

爲什麼'id'而不是'subcategoryID'? –

+0

你說得對。謝謝你的觀點。 –

+0

這不起作用。 – Rob

相關問題