2012-08-23 42 views
0

我已将模型中的字符串属性转换为隐式运算符与我的自定义类型EngNum之间的类。我这样做是为了让这种类型的所有事件都具有我的自定义编辑器,即使类型应该像字符串一样使用。MVC2绑定不适用于自定义类型

我的问题是该属性不再正确绑定到我的模型,即使值在POST中的窗体中。

public class EngNum 
{ 
    private string internalString; 

    public EngNum() { } 

    public EngNum(string number) 
    { 
     internalString = number; 
    } 

    public static implicit operator string(EngNumnumber) 
    { 
     return number == null ? null : number.internalString; 
    } 

    public static implicit operator EngNum(string number) 
    { 
     return new EngineerNumber() { internalString = number }; 
    } 
} 

,这里是现在它在视图中显示:

EngNum类型见下文

<%= Html.EditorFor(m => m.EngineerNumber) %> 

下面是它的编者:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ThreeSixtyScheduling.Models.EngineerNumber>" %> 
<%@ Import Namespace="ThreeSixtyScheduling.BLL.Utilities" %> 
<%= Html.ComboBoxFor(m => m, 
        new { @class = "EngineerNumber" }, 
        Url.Action("MasternautEngineers", "Data", new { area = (string)null }), 
        Model, 0) %> 

ComboBoxFor呈现一个TextBoxFor以及一些jQuery。

在我从视图中取出这段代码并将其放入编辑器之前,它工作正常。

如何在回发中正确地绑定属性?


在控制器动作已与EngineerNumber属性相关联的以下异常的ModelState

{System.InvalidOperationException:从类型 'System.String' 的参数转换为类型“ThreeSixtyScheduling .Models.EngNum'失败 ,因为没有类型转换器可以在这些类型之间进行转换。在在 的System.Web在 System.Web.Mvc.ValueProviderResult.UnwrapPossibleArrayType System.Web.Mvc.ValueProviderResult.ConvertSimpleType(CultureInfo的 培养,对象的值,类型destinationType)(CultureInfo的 培养,对象的值,类型destinationType)。 Mvc.ValueProviderResult.ConvertTo(类型类型,CultureInfo的 培养)在 System.Web.Mvc.DefaultModelBinder.ConvertProviderResult(ModelStateDictionary 的ModelState,字符串modelStateKey,valueProviderResult valueProviderResult,类型destinationType)}


控制器方法(和模型的类型):

[HttpPost] 
public ActionResult CreateStockcheckJob(CreateStockcheckJobModel viewModel) 

public class CreateStockcheckJobModel 
{ 
    [Required] 
    [DisplayName("Engineer Number")] 
    public EngNum EngineerNumber { get; set; } 

    [Required] 
    [DisplayName("Date and Time")] 
    public DateTime DateAndTime { get; set; } 

    public bool JobCreated { get; set; } 

    public CreateStockcheckJobModel() 
    { 
     DateAndTime = DateTime.Today.WithTimeOfDay(8, 0, 0); 
    } 
} 

代码为ComboBoxFor

public static MvcHtmlString ComboBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, 
                   Expression<Func<TModel, TProperty>> expression, 
                   object htmlProperties, 
                   string ajaxJSONLocation, 
                   string selectedValue, 
                   int minLength) 
    { 
     return ComboBoxFor(htmlHelper, expression, htmlProperties, ajaxJSONLocation, selectedValue, minLength, false, string.Empty); 
    } 

    public static MvcHtmlString ComboBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, 
                   Expression<Func<TModel, TProperty>> expression, 
                   object htmlProperties, 
                   string ajaxJSONLocation, 
                   string selectedValue, 
                   int minLength, 
                   bool hideId, 
                   string selectCallbackScript) 
    { 
     var textboxHTML = htmlHelper.TextBoxFor(expression, htmlProperties); 

     var scriptString = @"<script type=""text/javascript""> 
$(function() { 
    " + (string.IsNullOrEmpty(selectedValue) ? "$('#" + htmlHelper.IdFor(expression) + @"').val('')" : string.Empty) + @" 
    $.getJSON('" + ajaxJSONLocation + @"', function(result) { 

     $('#" + htmlHelper.IdFor(expression) + @"').autocomplete({ 
                    minLength: " + minLength.ToString() + @", 
                    source: function(request, response) { 
                       dataArray = new Array(); 
                       $.each(result, function(k, v) { 
                        if (v.value.toUpperCase().indexOf(request.term.toUpperCase()) != -1 || 
                         v.desc.toUpperCase().indexOf(request.term.toUpperCase()) != -1) { 
                         dataArray.push(v); 
                        } 
                       }); 
                       response(dataArray); 
                    }, 
                    focus: function(event, ui) {}, 
                    select: function(event, ui) { 
                    $('#" + htmlHelper.IdFor(expression) + @"').val(ui.item.value); 
                    " + selectCallbackScript + @" 
                    return false; } 
                  }) 
                .data(""autocomplete"")._renderItem = function (ul, item) { 
                 return $(""<li></li>"") 
                   .data(""item.autocomplete"", item) 
                   .append(""<a>"" + " + (hideId ? string.Empty : @"item.value + ""<br/>"" + ") + @"""<span>"" + item.desc + ""</span></a>"") 
                   .appendTo(ul); 
                }; 
    }); 
}); 
</script>"; 

     return MvcHtmlString.Create(textboxHTML.ToString() + scriptString); 
    } 
+0

你能告诉我们'ComboBoxFor'扩展方法吗?此外,您正尝试将表单提交给控制器操作的签名。 –

回答

1

模型绑定是不会打电话给你的自定义隐含操作。您需要拥有一个具有相同名称的公共财产或编写自定义模型联编程序。通常,您不需要在视图模型上使用隐式运算符。

+0

我不太理解您的答案中的解决方案。公共财产在哪里,并与什么相同的名称?我试着给我的'EngNum'类型添加一个'EngineerNumber'属性,但是这个功能不起作用。 –

+0

2种可能性:在您的'CreateStockcheckJobModel'类中,您只需使用:'public string EngineerNumber {get;组; }'或者如果你想使用一个复杂的子模型,你可以去掉带参数的隐式运算符和构造函数,并为它添加一个字符串属性(名称不同于包含的类)。在这种情况下,你将使用'<%= Html.ComboBoxFor(m => m.Number,new {@class =“EngineerNumber”},Url.Action(“MasternautEngineers”,“Data”,new {area = (string)null}),Model.Number,0)%>'。 –

1

您需要通过TypeConverterAttribute将类型转换器添加到您的课程。此类型转换器将被ASP.NET MVC用于将字符串转换为您的类型。

相关问题