2011-09-13 21 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