2011-09-13 20 views
4

很抱歉在這裏有很多代碼...我儘量保持它儘可能短:MVC3 LowerCase路由值的行爲與UpperCase不同嗎?

我已經寫了(主要是從這裏盜取)一個HtmlHelper擴展來寫出一個RadioButton(分組),基於一個枚舉。我也把我的路線圖,以便它使用一個枚舉,而不是「ID」等

我有兩個枚舉的(在這個例子中)CurrencyType和StatusType

當我致電URL/GBP /打開,我HtmlHelper正常工作,並設置單選按鈕的值,並選中GBP和Open。

當我致電URL/GBP /開放 - 的助手仍然將檢查值並顯示工作...但是當單選按鈕()ToHtmlString()被稱爲「選中」不存在???? 使用默認路由,單選按鈕仍然正確設置?

如果你斷點返回的SelectList,那麼你可以看到選擇的選項設置正確,所以我有點難以確定問題出現在哪裏?


Empty MVC3 website called Area36...Area 51 was taken ;) 


using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 
using System.Web.Mvc.Html; 
using System.Linq.Expressions; 
using System.Text; 

namespace Area36.Models 
{ 
    public static class Extensions 
    { 
     public static SelectList ToSelectList<TEnum>(this TEnum enumObj) 
     { 
      var values = from TEnum e in Enum.GetValues(typeof(TEnum)) 
         select new { ID = e, Name = e }; 
      return new SelectList(values, "Id", "Name", enumObj); 
     } 

     public static void AppendFormatLine(this StringBuilder sb, string format, params object[] args) 
     { 
      sb.AppendFormat(format, args); 
      sb.AppendLine(); 
     } 

     public static MvcHtmlString RadioButtonForEnum<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, string fieldSet) 
     { 
      var metaData = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData); 
      var e = (TProperty)Enum.Parse(typeof(TProperty), metaData.Model.ToString()); 
      var selectList = e.ToSelectList(); 
      var sb = new StringBuilder(); 

      if (selectList != null) 
      { 
       sb.AppendFormatLine("<fieldset><legend>{0}</legend>", fieldSet); 
       foreach (SelectListItem item in selectList) 
       { 
        var id = string.Format("{0}_{1}", metaData.PropertyName, item.Value); 
        if (htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix != string.Empty) 
         id.Insert(0, string.Format("{0}_", htmlHelper.ViewData.TemplateInfo.HtmlFieldPrefix)); 

        var label = htmlHelper.Label(id, HttpUtility.HtmlEncode(item.Text)); 
        var radio = htmlHelper.RadioButton(name: metaData.PropertyName, value: item.Value, isChecked: item.Selected, htmlAttributes: new { id = id }).ToHtmlString(); 

        sb.AppendFormatLine("<div class=\"radio_{0}\">{1}{2}</div>", metaData.PropertyName, radio, label); 
       } 
       sb.AppendLine("</fieldset>"); 
      } 

      return MvcHtmlString.Create(sb.ToString()); 
     } 
    } 
} 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using System.Web.Mvc; 
using Area36.Models; 

namespace Area36.Controllers 
{ 
    public class HomeController : Controller 
    { 
     // 
     // GET: /Home/ 

     public ActionResult Index(CurrencyType currency, StatusType status) 
     { 
      return View(new ViewModel { Currency = currency, Status = status }); 
     } 

    } 
} 

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace Area36.Models 
{ 
    public class ViewModel 
    { 
     public CurrencyType Currency { get; set; } 
     public StatusType Status { get; set; } 
    } 
} 

@using Area36.Models 
@model Area36.Models.ViewModel 


@{ 
    ViewBag.Title = "Index"; 
} 

<h2>Index</h2> 
@Html.RadioButtonForEnum(m => m.Currency, "Currency") 
@Html.RadioButtonForEnum(m => m.Status, "Status") 

public static void RegisterRoutes(RouteCollection routes) 
     { 
      routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

      routes.MapRoute(
       "Default", // Route name 
       "{currency}/{status}", // URL with parameters 
       new { controller = "Home", action = "Index", currency = CurrencyType.EUR, status = StatusType.Closed} // Parameter defaults 
      ); 

     } 

回答

1

我嘗試了各種方法來解決這個問題。強制傳遞UpperCase值。最令人驚訝的是,當我如下所示爲所有單選按鈕傳遞「true」時,即使輸出相同,按鈕也僅用於大寫url。

var radio = htmlHelper.RadioButton(metaData.PropertyName, item.Value, true, new { id = id }).ToHtmlString(); 

隨着一些RND與此代碼和一些谷歌上搜索,我發現this。 如果您查看 以下是MVC3-rtm的代碼。在這裏你可以看到isChecked的值根據ModelState被修改,如果你在調試模式下檢查了modelState.Values [index] .AttemptedValue的值,它顯然是小寫的(對於「gbp/open」)。這就是爲什麼小寫url不會顯示checked屬性。

private IHtmlString BuildRadioButton(string name, object value, bool? isChecked, IDictionary<string, object> attributes) { 
     string valueString = ConvertTo(value, typeof(string)) as string; 

     TagBuilder builder = new TagBuilder("input"); 
     builder.MergeAttribute("type", "radio", true); 
     builder.GenerateId(name); 
     builder.MergeAttributes(attributes, replaceExisting: true); 

     builder.MergeAttribute("value", valueString, replaceExisting: true); 
     builder.MergeAttribute("name", name, replaceExisting: true); 

     var modelState = ModelState[name]; 
     string modelValue = null; 
     if (modelState != null) { 
      modelValue = ConvertTo(modelState.Value, typeof(string)) as string; 
      isChecked = isChecked ?? String.Equals(modelValue, valueString, StringComparison.OrdinalIgnoreCase); 
     } 

     if (isChecked.HasValue) { 
      // Overrides attribute values 
      if (isChecked.Value) { 
       builder.MergeAttribute("checked", "checked", true); 
      } 
      else { 
       builder.Attributes.Remove("checked"); 
      } 
     } 

     AddErrorClass(builder, name); 

     return builder.ToHtmlString(TagRenderMode.SelfClosing); 
    } 
+0

謝謝:)有了這些知識,我添加了一個檢查的結果字符串,如果該項目被選中,但不包含「檢查=檢查」,然後我手動添加。 – BlueChippy