2011-08-04 191 views
29

我試圖建立在MVC自定義路線採取URL從另一個系統的格式如下:如何在ASP.NET MVC中使用查詢字符串路由URL?

../ABC/ABC01?Key=123&Group=456

第二ABC後,01是步數,這將改變和重點和組參數會改變。我需要將其路由到控制器中的一個動作,步驟數字鍵和組作爲參數。我已經嘗試下面的代碼但它拋出一個異常:

代碼:

routes.MapRoute(
    "OpenCase", 
    "ABC/ABC{stepNo}?Key={key}&Group={group}", 
    new {controller = "ABC1", action = "OpenCase"} 
); 

例外:

`The route URL cannot start with a '/' or '~' character and it cannot contain a '?' character.` 

回答

35

不能包含在路線查詢字符串。嘗試用這樣的路線:

routes.MapRoute("OpenCase", "ABC/ABC{stepNo}", 
    new { controller = "ABC1", action = "OpenCase" }); 

然後,控制器上添加一個方法是這樣的:

public class ABC1 : Controller 
{ 
    public ActionResult OpenCase(string stepno, string key, string group) 
    { 
     // do stuff here 
     return View(); 
    }   
} 

ASP.NET MVC會自動在方法的查詢字符串參數的參數映射控制器。

4

當定義路線,你不能在路線的開始使用/

routes.MapRoute("OpenCase", 
    "/ABC/{controller}/{key}/{group}", <-- Bad; see/at beginning 
    new { controller = "", action = "OpenCase" }, 
    new { key = @"\d+", group = @"\d+" } 
    ); 

routes.MapRoute("OpenCase", 
    "ABC/{controller}/{key}/{group}", <-- Good; No/at beginning 
    new { controller = "", action = "OpenCase" }, 
    new { key = @"\d+", group = @"\d+" } 
    ); 

試試這個:

routes.MapRoute("OpenCase", 
    "ABC/{controller}/{key}/{group}", 
    new { controller = "", action = "OpenCase" }, 
    new { key = @"\d+", group = @"\d+" } 
    ); 

那麼你的操作應該如下所示:

public ActionResult OpenCase(int key, int group) 
{ 
    //do stuff here 
} 

它看起來像你放在一起stepNo和「 ABC「來得到一個控制器,它是ABC1。這就是爲什麼我用{controller}替換了該部分的URL。

由於您還有一個定義'key'和'group'的路由,上面的路由也會捕獲您的初始URL並將其發送到操作。

1

沒有理由在新的ASP.NET MVC項目中使用基於查詢字符串的路由。對於從傳統ASP.NET項目轉換而來的舊項目,您希望保留URL,這會很有用。

一個解決方案可以是屬性路由。

另一種解決方案可以通過從RouteBase獲得書面方式自定義路由:

public class MyOldClassicAspRouting : RouteBase 
{ 

    public override RouteData GetRouteData(HttpContextBase httpContext) 
    { 
    if (httpContext.Request.Headers == null) //for unittest 
     return null; 

    var queryString = httpContext.Request.QueryString; 

    //add your logic here based on querystring 
    RouteData routeData = new RouteData(this, new MvcRouteHandler()); 
    routeData.Values.Add("controller", "..."); 
    routeData.Values.Add("action", "..."); 
    } 

    public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values) 
    { 
    //Implement your formating Url formating here 
    return null; 
    } 
} 

並註冊您的自定義路由類

public static void RegisterRoutes(RouteCollection routes) 
{ 
    ... 

    routes.Add(new MyOldClassicAspRouting()); 
} 
0

的查詢字符串參數通常是特定該控制器和該具體的應用邏輯。

因此,如果這不是寫在路線規則中,那麼它會更好,這是一般性的。

您可以通過以下方式在操作參數中嵌入對查詢字符串的檢測。

我認爲最好有一個Controller來處理StepNo。

public class ABC : Controller 
{ 
    public ActionResult OpenCase(OpenCaseArguments arg) 
    { 
     // do stuff here 
     // use arg.StepNo, arg.Key and arg.Group as You need 
     return View(); 
    }   
} 

public class OpenCaseArguments 
{ 
    private string _id; 
    public string id 
    { 
     get 
     { 
      return _id; 
     } 

     set 
     { 
      _id = value; // keep original value; 
      ParseQueryString(value); 
     } 
    } 

    public string StepNo { get; set; } 
    public string Key { get; set; } 
    public string Group { get; set; } 

    private void ParseQueryString(string qs) 
    { 
     var n = qs.IndexOf('?'); 
     if (n < 0) return; 
     StepNo = qs.Substring(0, n); // extract the first part eg. {stepNo} 
     NameValueCollection parms = HttpUtility.ParseQueryString(qs.Substring(n + 1)); 
     if (parms.Get("Key") != null) Key = parms.Get("Key"); 
     if (parms.Get("Group") != null) Group = parms.Get("Group"); 
    } 

} 

ModelBinder將{id}值分配給OpenCaseArguments的id字段。 set方法處理查詢字符串拆分邏輯。

並保持路由這種方式。注意路由在id參數中獲取你的查詢字符串。

routes.MapRoute(
    "OpenCase", 
    "ABC/OpenCase/{id}", 
    new {controller = "ABC", action = "OpenCase"} 
); 

我已經使用此方法獲取控制器操作的多個字段鍵值。

+0

請注意,MVC會自動使用QueryStringValueProvider解析查詢字符串。您只需在操作方法中獲取這些值就可以將與查詢字符串鍵相同名稱的參數添加到操作方法或模型中。沒有必要爲此構建您自己的查詢字符串解析器。 – NightOwl888

相關問題