如何将 http 请求转换为正确的对象?

发布于 2024-11-15 09:48:05 字数 1446 浏览 2 评论 0原文

在我的 ASP.Net MVC3 项目中,我创建了一个绑定基本模型的 ModelBinder。在我的视图中,我从继承自基本模型的模型创建一个对象。现在我想知道当我按下提交按钮时,哪个模型是通过 ModelBinder 中的反射创建的,但是如何呢?

ModelBinder:

public class MBTestBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        //need to know which Model was created -> convert into the right object
        //reflection?
    }
}

Models:

[ModelBinder(typeof(MBTestBinder))]
public class MBTest
{
    public string Name { get; set; }
    public MBTest()  {}
}

public class MBAbl : MBTest
{
    public MBAbl()  {}
    public string House { get; set; }
}

View:

@model ModelBinderProject.Models.MBTest

@using (Html.BeginForm("Index", "Home")) {
<fieldset>
    <div class="editor-field">
        @Html.EditorForModel(Model)
    </div>
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>

Controller:

public ActionResult Create(MBTest testItem)
{
    //on init get a view from a class that hast inherit the class MBTest
    if (testItem.Name == null ) testItem = new MBAbl();

    return View(testItem);
}

edit:

使用 bindingContext.ValueProvider.GetValue("House") 我可以获取表单的值,但 bindingContext.ModelType 认为我的模型是MBTest

In my ASP.Net MVC3 project I have created a ModelBinder which binds a basemodel. In my View i create a object from a Model that inherit from my basemodel. Now i wan´t to know which Model was created via reflection in my ModelBinder when i press the submit-button, but how?

ModelBinder:

public class MBTestBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        //need to know which Model was created -> convert into the right object
        //reflection?
    }
}

Models:

[ModelBinder(typeof(MBTestBinder))]
public class MBTest
{
    public string Name { get; set; }
    public MBTest()  {}
}

public class MBAbl : MBTest
{
    public MBAbl()  {}
    public string House { get; set; }
}

View:

@model ModelBinderProject.Models.MBTest

@using (Html.BeginForm("Index", "Home")) {
<fieldset>
    <div class="editor-field">
        @Html.EditorForModel(Model)
    </div>
    <p>
        <input type="submit" value="Create" />
    </p>
</fieldset>

Controller:

public ActionResult Create(MBTest testItem)
{
    //on init get a view from a class that hast inherit the class MBTest
    if (testItem.Name == null ) testItem = new MBAbl();

    return View(testItem);
}

edit:

with bindingContext.ValueProvider.GetValue("House") i can get the value of the Form but bindingContext.ModelType thinks that my Model is MBTest

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

信仰 2024-11-22 09:48:05

查看 ModelBindingContext 文档。

根据评论进行编辑

public class MBTestBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = bindingContext.ValueProvider.GetValue("Name");

        if (result == null || string.IsNullOrEmpty(result.AttemptedValue))
           return new MBAbl();
        else
           return new MBTest();
    }
}

Check the ModelBindingContext documentation.

Edited based on comments

public class MBTestBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var result = bindingContext.ValueProvider.GetValue("Name");

        if (result == null || string.IsNullOrEmpty(result.AttemptedValue))
           return new MBAbl();
        else
           return new MBTest();
    }
}
神经暖 2024-11-22 09:48:05

最后,我通过在模型中携带模型名称并在模型绑定器中动态创建正确的模型的解决方法解决了这个问题。
如果您知道更好的解决方案,请告诉我:-)

HomeController:

// CREATE
public ActionResult About(MBTest testItem)
{
    if (testItem == null)
    {
        testItem = new MBAbl();
        testItem.Model = "MBAbl";
    }

    return View(testItem);
}

Models:

public class MBTest
{
    public MBTest()  {}

    [HiddenInput]
    public string Model { get; set; }

    public string Name { get; set; }
}

public class MBAbl : MBTest
{
    public MBAbl()  {}

    public string House { get; set; }
}

public class MBAb2 : MBTest
{
    ...
}

ModelBinder:

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    if (controllerContext == null) throw new ArgumentNullException("controllerContext");
    if (bindingContext == null) throw new ArgumentNullException("bindingContext");

    //string 'Model' is needed in the base class
    var modelType = bindingContext.ValueProvider.GetValue("Model");

    if (modelType != null && !string.IsNullOrEmpty(modelType.AttemptedValue))
    {
        string projectName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

        Type classtype = Type.GetType(string.Format("{0}.Models.{1}", projectName, modelType.AttemptedValue));
        PropertyInfo[] properties = classtype.GetProperties();

        var classObject = classtype.GetConstructor(new Type[] { }).Invoke(null);

        foreach (PropertyInfo propertie in properties)
        {
            var value = bindingContext.ValueProvider.GetValue(propertie.Name).AttemptedValue;
            classtype.GetProperty(propertie.Name).SetValue(classObject, value, null);
        }

        return classObject;
    }
    return null;
}

Finaly i solved it with the workaround of carrying the name of the model in my model and dynamically create the right model in the modelbinder.
If you know a better solution plz show me :-)

HomeController:

// CREATE
public ActionResult About(MBTest testItem)
{
    if (testItem == null)
    {
        testItem = new MBAbl();
        testItem.Model = "MBAbl";
    }

    return View(testItem);
}

Models:

public class MBTest
{
    public MBTest()  {}

    [HiddenInput]
    public string Model { get; set; }

    public string Name { get; set; }
}

public class MBAbl : MBTest
{
    public MBAbl()  {}

    public string House { get; set; }
}

public class MBAb2 : MBTest
{
    ...
}

ModelBinder:

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
    if (controllerContext == null) throw new ArgumentNullException("controllerContext");
    if (bindingContext == null) throw new ArgumentNullException("bindingContext");

    //string 'Model' is needed in the base class
    var modelType = bindingContext.ValueProvider.GetValue("Model");

    if (modelType != null && !string.IsNullOrEmpty(modelType.AttemptedValue))
    {
        string projectName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

        Type classtype = Type.GetType(string.Format("{0}.Models.{1}", projectName, modelType.AttemptedValue));
        PropertyInfo[] properties = classtype.GetProperties();

        var classObject = classtype.GetConstructor(new Type[] { }).Invoke(null);

        foreach (PropertyInfo propertie in properties)
        {
            var value = bindingContext.ValueProvider.GetValue(propertie.Name).AttemptedValue;
            classtype.GetProperty(propertie.Name).SetValue(classObject, value, null);
        }

        return classObject;
    }
    return null;
}
落在眉间の轻吻 2024-11-22 09:48:05

试试这个:

public class ModelBinder : DefaultModelBinder, IModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var typeValue = bindingContext.ValueProvider.GetValue("ModelType");
        var type = Type.GetType("Namespace.a.b." + typeValue.AttemptedValue.ToString());

        var model = Activator.CreateInstance(type);

        //Change the model
        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
        bindingContext.ModelMetadata.Model = model;

        //Here, we used the default model binder of the mvc
        return base.BindModel(controllerContext, bindingContext);;
    }
}

Try this:

public class ModelBinder : DefaultModelBinder, IModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var typeValue = bindingContext.ValueProvider.GetValue("ModelType");
        var type = Type.GetType("Namespace.a.b." + typeValue.AttemptedValue.ToString());

        var model = Activator.CreateInstance(type);

        //Change the model
        bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
        bindingContext.ModelMetadata.Model = model;

        //Here, we used the default model binder of the mvc
        return base.BindModel(controllerContext, bindingContext);;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文