2010-10-20 80 views
1

有沒有辦法將一組枚舉傳遞給ActionMethod(在GET上)?將枚舉傳遞給ASP.NET MVC ActionMethod

舉例來說,如果我有以下枚舉定義:

enum DaysEnum {Sat, Sun, Mon, Tue, Wed, Thu, Fri}; 

而且,我有一個ActionMethod定義:

ActionResult SampleActionMethod (List<DaysEnum> days) 

有沒有一種方法,我可以呈現,在視圖中,一個可傳入DayEnums集合的URL。喜歡的東西:

var someDays = new List<DaysEnum> {DaysEnum.Sat, DaysEnum.Sun, DaysEnum.Mon}; 

Url.Route(new { days = someDays, controller="whatever", action="SampleActionMethod"}); 

默認的model binder似乎並不支持這一點,因爲我目前得到以下渲染:

http://.../System.Collections.Generic.List`1[DaysEnum] 

我知道我可以通過手動壓扁集合做到這一點比如說一個破折號字符串,然後在ActionMethod中重新創建集合,但我正在尋找更優雅的東西。各種blogposts談論傳遞集合,但更多的是關於什麼時候做POSTS。

回答

1
<%= Html.ActionLink("test enums", "SampleActionMethod", new RouteValueDictionary { 
    { "days[0]", DaysEnum.Sun }, { "days[1]", DaysEnum.Mon } 
}) %> 
+0

謝謝,這是有效的。唯一的問題是URL不再友好。因此,而不是http://控制器/動作/值1 /值2/...,我知道得到的http://控制器/動作參數1 =值1&參數2 =值2和天[0] =太陽和天[1] =週一儘管如此,它還是比手動綁定更好 – sohail 2010-10-20 11:08:56

0

我恐怕複雜的數據類型不能與GET請求來承載。 ü可以使用一些隱藏的價值觀和發佈數據,如果ü確實想發送這些值作爲集合

+1

Darin的答案似乎有效,但犧牲了友好的URL。 – sohail 2010-10-20 11:09:42

+2

是的,它不會發送複雜的類型。它相當手動序列化數據,再次通過模型綁定器將其放回到一起 – 2010-10-20 11:37:46

2

我們這樣做是使用控制器參數的自定義模型粘合劑和擴展方法以在URL參數。

模型綁定看起來是這樣的:

/// <summary> 
/// Custom binder class. 
/// </summary> 
public class DaysEnumModelBinder : IModelBinder 
{ 
    /// <summary> 
    /// Convert a comma-separated string to a list. 
    /// </summary> 
    /// <param name="rawValue">Raw value from binding context.</param> 
    /// <returns>List of enum values.</returns> 
    public static List<DaysEnum> ConvertArray(object rawValue) 
    { 
     var results = new List<DaysEnum>(); 

     string[] query = rawValue as string[]; 

     if (query != null && query.Length != 0) 
     { 
      string[] parts = query[0].Split(','); 

      foreach (string part in parts) 
      { 
       try 
       { 
        DaysEnum resultValue = (DaysEnum)Enum.Parse(typeof(DaysEnum), part, true); 
        results.Add(resultValue); 
       } 
       catch (ArgumentException) 
       { 
       } 
      } 
     } 

     return results; 
    } 

    /// <summary> 
    /// Implement IModelBinder to bind a comma-separated array of int values to a single array. 
    /// </summary> 
    /// <param name="controllerContext">The controller context.</param> 
    /// <param name="bindingContext">The binding context.</param> 
    /// <returns>Int array where applied to the correct type of object.</returns> 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     if (!bindingContext.ValueProvider.ContainsPrefix(bindingContext.ModelName)) 
     { 
      return new DefaultModelBinder().BindModel(controllerContext, bindingContext); 
     } 

     if (bindingContext.ModelType == typeof(DaysEnum[])) 
     { 
      List<DaysEnum> results = ConvertArray(bindingContext.ValueProvider.GetValue(bindingContext.ModelName).RawValue); 

      return results.ToArray(); 
     } 

     return new DefaultModelBinder().BindModel(controllerContext, bindingContext); 
    } 
} 

然後在您的控制器方法你掛鉤的粘結劑像這樣:

ActionResult MyMethod([ModelBinder(typeof(DaysEnumModelBinder))] DaysEnum[] days) 
{ 
    ... 
} 

最後在視圖呈現URL的東西,如string.Join(",", days.Select(d => d.ToString()))

+0

謝謝。你已經基本上做了什麼,我試圖避免(即手動壓平及去壓平的集合,如在我的問題說),但它是有用的知道,這至少可以在自定義模型綁定進行封裝。如果Darin的解決方案沒有工作,我會用這樣的事情。 – sohail 2010-10-20 11:12:24

+0

是啊,對我們的要求是使用一個單一的請求參數,所以這是必要的。 – 2010-10-20 11:16:11