可以抽象类是在控制器的动作参数? [英] Can abstract class be a parameter in a controller's action?
问题描述
我有一个控制器,这是被称为与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屋!