可以抽象类是在控制器的动作参数? [英] Can abstract class be a parameter in a controller's action?

查看:158
本文介绍了可以抽象类是在控制器的动作参数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个控制器,这是被称为与AJAX里面的动作功能。这项行动正在采取的一个参数。客户端,我构造一个JSON对象,它应该序列成1的参数。我遇到的问题是参数类被声明为抽象的。因此,它不能被实例化。当AJAX打的动作,我得到如下:

I have an Action function inside of a Controller, which is being called with AJAX. That Action is taking in 1 parameter. Client side, I construct a JSON object which should serialize into that 1 parameter. The problem I ran into is that the parameter class is declared as abstract. Thus, it cannot be instantiated. When AJAX hits that Action, I get the following:

不能创建一个抽象类。

堆栈跟踪:

[的MissingMethodException:无法创建   一个抽象类。]
  System.RuntimeTypeHandle.CreateInstance(RuntimeType   型,布尔publicOnly,布尔   NOCHECK,布尔和放大器; canBeCached,   RuntimeMethodHandleInternal和放大器;构造函数,   布尔和放大器; bNeedSecurityCheck)+ 0
  System.RuntimeType.CreateInstanceSlow(布尔   publicOnly,布尔skipCheckThis,   布尔fillCache)+98
  System.RuntimeType.CreateInstanceDefaultCtor(布尔   publicOnly,布尔   skipVisibilityChecks,布尔   skipCheckThis,布尔fillCache)+241   System.Activator.CreateInstance(类型   型,布尔非公开)+69   ...............

[MissingMethodException: Cannot create an abstract class.]
System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) +0
System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache) +98
System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipVisibilityChecks, Boolean skipCheckThis, Boolean fillCache) +241 System.Activator.CreateInstance(Type type, Boolean nonPublic) +69 ...............

有没有办法拉过这样的场景,而无需创建一个不同的参数对象,未声明的参数对象为抽象,或挖掘到MVC的机制?谢谢你。

Is there any way to pull off such a scenario without creating a different parameter object, "un-declaring" the parameter object as abstract, or digging into mechanics of MVC? Thanks.

更新:我目前正在与后端开发人员来调整它们的对象。无论哪种方式,我认为这将是最终的解决办法。谢谢大家对你的答案。

UPDATE: I'm currently working with back-end developers to tweak their objects. Either way, I think that would be the ultimate solution. Thank you all for your answers.

推荐答案

更新:示例现在使用AJAX JSON POST

Update: Example now uses a AJAX JSON POST

如果你必须使用一个抽象类,你可以提供一个自定义模型粘合剂以创建具体的实例。一个例子如下所示:

If you must use an abstract type, you could provide a custom model binder to create the concrete instance. An example is shown below:

型号/模型绑定

public abstract class Student
{
    public abstract int Age { get; set; }
    public abstract string Name { get; set; }
}
public class GoodStudent : Student
{
    public override int Age { get; set; }
    public override string Name { get; set; }
}
public class BadStudent : Student
{
    public override int Age { get; set; }
    public override string Name { get; set; }
}
public class StudentBinder : IModelBinder
{
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var values = (ValueProviderCollection) bindingContext.ValueProvider;
        var age = (int) values.GetValue("Age").ConvertTo(typeof (int));
        var name = (string) values.GetValue("Name").ConvertTo(typeof(string));
        return age > 10 ? (Student) new GoodStudent { Age = age, Name = name } : new BadStudent { Age = age, Name = name };
    }
}

控制器操作

public ActionResult Index()
{
    return View(new GoodStudent { Age = 13, Name = "John Smith" });
}
[HttpPost]
public ActionResult Index(Student student)
{
    return View(student);
}

查看

@model AbstractTest.Models.Student

@using (Html.BeginForm())
{
    <div id="StudentEditor">
        <p>Age @Html.TextBoxFor(m => m.Age)</p>
        <p>Name @Html.TextBoxFor(m => m.Name)</p>
        <p><input type="button" value="Save" id="Save" /></p>
    </div>
}

<script type="text/javascript">
    $('document').ready(function () {
        $('input#Save').click(function () {
            $.ajax({
                url: '@Ajax.JavaScriptStringEncode(Url.Action("Index"))',
                type: 'POST',
                data: GetStudentJsonData($('div#StudentEditor')),
                contentType: 'application/json; charset=utf-8',
                success: function (data, status, jqxhr) { window.location.href = '@Url.Action("Index")'; }
            });
        });
    });

    var GetStudentJsonData = function ($container) {
             return JSON.stringify({
                 'Age': $container.find('input#Age').attr('value'),
                 'Name': $container.find('input#Name').attr('value')
             });
         };
</script>

添加到的Global.asax.cs

protected void Application_Start()
{
    ...
    ModelBinders.Binders.Add(new KeyValuePair<Type, IModelBinder>(typeof(Student), new StudentBinder()));
}

这篇关于可以抽象类是在控制器的动作参数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆