2010-08-04 70 views
0

我正在嘗試將REST-行爲寫入到我的ASP.NET MVC2應用中,但我很難弄清楚如何使路由按我的意思工作。在ASP.NET MVC中基於請求的數據類型的路由

我想我的路由的工作是這樣的:

/Users/Get/1 <- returns a regular HTML-based reply 
/Users/Get.xml/1 <- returns the data from Get as XML 
/Users/Get.json/1 <- returns the data as JSon 

我試過設置路線是這樣的:

routes.MapRoute("Rest", 
"{controller}/{action}{format}/{id}" (...) 

但抱怨我需要之間的分隔符{}行動和{格式}

還執行以下操作:

routes.MapRoute("Rest", 
    "{controller}/{action}.{format}/{id}" (...) 

使得/ Users/Get/1無效(它必須是/Users/Get./1,這是不可接受的)

有什麼建議嗎?

-------------編輯-------------------------------- ----

我有一個解決方案的權利,但我真的不喜歡它:

routes.MapRoute(
      "DefaultWithFormat", // Route name 
      "{controller}/{action}.{format}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", format = "HTML", id = UrlParameter.Optional } // Parameter defaults 
     ); 
     routes.MapRoute(
      "Default", // Route name 
      "{controller}/{action}/{id}", // URL with parameters 
      new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 
     ); 

這工作既/Users/Get.whateverFormat/1也/用戶/獲取/ 1

這樣做的原因是,當我剛剛執行/ Users/Get/1(不帶.format)時,它會跳過第一個路徑,然後轉到下一個不包含格式的路徑。 要處理我已經創建了一個ActionFilterAttribute返回並覆蓋這樣的OnActionExecuted方法:

var type = filterContext.RouteData.Values["format"]; 
if (type != null && attributes != null) 
{ 
    if (type == "HTML") return; 
    if (type.ToString().ToLower() == "xml" && attributes.Any(a => a.AllowedTypes.Any(a2 => a2 == ResponseType.XML))) 
    { 
     filterContext.Result = new XmlResult(filterContext.Controller.ViewData.Model); 
     filterContext.HttpContext.Response.Clear(); 
     filterContext.HttpContext.Response.ContentType = "text/xml"; 
     return; 
    } 
    if (type.ToString().ToLower() == "json" && attributes.Any(a => a.AllowedTypes.Any(a2 => a2 == ResponseType.JSON))) 
    { 
     filterContext.Result = new JsonResult() { Data = (filterContext.Controller.ViewData.Model), JsonRequestBehavior = JsonRequestBehavior.AllowGet }; 
     filterContext.HttpContext.Response.Clear(); 
     filterContext.HttpContext.Response.ContentType = "text/json"; 
     return; 
    } 
} 

而且我也有一個ResponseTypeAttribute,讓我來裝飾什麼的返回類型,他們應該讓操作:

[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] 
public sealed class ResponseTypeAttribute : Attribute 
{ 
    List<ResponseType> allowedTypes; 

    public List<ResponseType> AllowedTypes 
    { 
     get { return allowedTypes; } 
     set { allowedTypes = value; } 
    } 

    public ResponseTypeAttribute(params ResponseType[] allowedTypes) 
    { 
     this.allowedTypes = new List<ResponseType>(); 
     this.allowedTypes.AddRange(allowedTypes); 
    } 


} 

public enum ResponseType 
{ 
    XML, JSON 
} 

XmlResult只是一個簡單的對象序列化器。

回答

0

Brad Wilson與標題高級ASP.NET MVC2進行了一次談話,他展示了一個示例,說明如何實現您想要的功能。您也可以下載幻燈片和示例代碼在這裏:

http://bradwilson.typepad.com/blog/talks.html

(這是頁面上的第一講,如果我記得很清楚寧靜的URL是在講第一個主題)

+0

並沒有真正幫助我,因爲幻燈片顯示:「演示 - 支持類似REST的URL」,並且示例代碼中沒有示例:) – 2010-08-04 08:09:42

+0

我已經看過這段視頻:http://events.boostweb20的.com /活動/ SeattleCodeCamp2010 /#狀態= sessionCode%242003-4。如果你有時間看看它。 :)它確實顯示了關於寧靜的URL的演示...... – apolka 2010-08-04 09:04:10

+0

現在,這是一個非常甜蜜的解決方案! :D – 2010-08-04 10:30:28

0

有無您嘗試設置的html的默認值?

0

也許這是一個選項(使用'/'而不是''。「):

routes.MapRoute(
     "Rest1", 
     "Users/Get/{format}/{id}", 
     new { controller = "Users", action = "Get", format = "HTML" } 
     ); 

然後

public class UsersController : Controller { 
    public ActionResult Get(string format, int id) { 
     switch (format) { 
     case "json": 
      break; 
     case "xml": 
      break; 
     default: 
      break; 
     } 
     return new ContentResult(); // Or other result as required. 
    } 
} 
+0

當然,但這不是我的問題;) – 2010-08-04 08:48:44

0

另一個想法:

routes.MapRoute(
    "Rest1", 
    "Users/Get/{id}.{format}", 
    new { controller = "Users", action = "Get", format = "HTML" } 
    ); 

然後在CONTROLER方法添加一些代碼retreaving ID和格式

+0

那麼/用戶/獲取/ 1不會工作...我需要寫「/用戶/獲取/ 1」。爲了路線工作... – 2010-08-04 08:35:14