开发者

ASP.NET MVC (3) Binding POST value to 'object' type makes the object a System.String[], why?

So, I have a search form in my website which posts Search.Value as a parameter where in the project there is a class called Search with a property Value which is an object. When the value is bound by the model binder, object is always System.String[] regardless if I pass in a single number, a single word or anything else.

Can someone explain to me why that is, or if I can make it stop doing that?

Here's the code:

// Search.cs
public sealed class Search {
    private object _Value = null;

    public object Value {
        get {
            return this._Value;
        }
        set {
            if (value != null) {
                this._Value = value;

                this.IsInt32 = (this._Value is Int32);
                this.IsString = (this._Value is String);
            };
        }
    }

    public bool IsInt32 { get; set; }
    public bool IsString { get; set; }
}

// SearchController.cs
[HttpPost]
public ActionResult List(
    [Bind(Prefix = "Search", Include = "Value")] Search Search) {
    return th开发者_开发技巧is.View();
}

// Form HTML
<form action="/Administration/Search" method="post">
    @Html.TextBox("Search.Value", Model.Search.Value, new { type = "search", placeholder = "Search", size = 48, required = string.Empty })
    <input type="submit" value="&#8981;" />
</form>

UPDATE

Per @Darin's suggestion and example I've made a custom binder and it seems to be working so far. Here's the code if anyone else runs into this, modify as needed of course:

public class SearchModelBinder : DefaultModelBinder {
    public override object BindModel(
        ControllerContext ControllerContext,
        ModelBindingContext BindingContext) {
        if (BindingContext == null) {
            throw new ArgumentNullException("BindingContext");
        };

        ValueProviderResult ValueResult = BindingContext.ValueProvider.GetValue(BindingContext.ModelName + ".Value");

        if (ValueResult == null) {
            return (null);
        };

        string Value = ValueResult.AttemptedValue;

        if (String.IsNullOrEmpty(Value)) {
            return (null);
        };

        int Int;

        if (int.TryParse(Value, out Int)) {
            return new Search {
                Value = Convert.ToInt32(Value)
            };
        };

        long Long;

        if (long.TryParse(Value, out Long)) {
            return new Search {
                Value = Convert.ToInt64(Value)
            };
        };

        return new Search {
            Value = Value
        };
    }
}


No idea what you are trying to achieve, why are you using object, ... but you could write a custom model binder for this Search model. This model binder will assign directly the parameter that is sent in the request to the Value property:

public class SearchModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Value");
        if (value != null)
        {
            return new Search
            {
                Value = value.AttemptedValue
            };
        }
        return base.BindModel(controllerContext, bindingContext);
    }
}

which you could register in Global.asax:

ModelBinders.Binders.Add(typeof(Search), new SearchModelBinder());
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜