C# 抽象类可以是控制器';什么行动?
我在控制器中有一个Action函数,它是用AJAX调用的。该操作在1个参数中执行。在客户端,我构造了一个JSON对象,该对象应序列化为该1参数。我遇到的问题是参数类被声明为抽象类。因此,它不能被实例化 当AJAX执行该操作时,我会得到以下结果: 无法创建抽象类 堆栈跟踪: [MissingMethodException:无法创建 抽象类。]C# 抽象类可以是控制器';什么行动?,c#,ajax,serialization,asp.net-mvc-3,C#,Ajax,Serialization,Asp.net Mvc 3,我在控制器中有一个Action函数,它是用AJAX调用的。该操作在1个参数中执行。在客户端,我构造了一个JSON对象,该对象应序列化为该1参数。我遇到的问题是参数类被声明为抽象类。因此,它不能被实例化 当AJAX执行该操作时,我会得到以下结果: 无法创建抽象类 堆栈跟踪: [MissingMethodException:无法创建 抽象类。] System.RuntimeTypeHandle.CreateInstance(RuntimeType 类型,仅布尔型,布尔型 noCheck、Boolea
System.RuntimeTypeHandle.CreateInstance(RuntimeType 类型,仅布尔型,布尔型 noCheck、Boolean和canBeCached, RuntimeMethodHandleInternal&ctor, 布尔值&bNeedSecurityCheck)+0
System.RuntimeType.CreateInstanceSlow(布尔值 publicOnly,布尔skipCheckThis, 布尔fillCache)+98
System.RuntimeType.CreateInstanceDefaultCtor(布尔值 publicOnly,Boolean skipVisibilityChecks,布尔型 skipCheckThis,布尔fillCache)+241 System.Activator.CreateInstance(类型 类型,布尔非公共)+69 有没有办法在不创建不同的参数对象、“取消声明”参数对象为抽象对象或深入研究MVC机制的情况下实现这种场景 更新
我目前正在与后端开发人员一起调整他们的对象。无论如何,我认为这将是最终的解决办法。谢谢大家的回答。没有-尝试将JSON反序列化为抽象类的对象毫无意义。你不能把它变成一个合适的类吗?你必须创建一个抽象类的子类并传递它。抽象类基本上不允许自己实例化。但是,如果您有一个C#方法,如:
protected void Foo(MyAbstractClass param1)
…然后您仍然可以向Foo传递从MyAbstractClass派生的类型的实例。因此,您可以创建一个具体的子类MyChildClass:MyAbstractClass
,并将其传递给您的方法,它应该仍然可以工作。您不必更改Foo
方法,但需要对C代码进行一些访问,以便创建MyChildClass
如果您使用泛型——例如,如果您的方法签名是:
protected void Foo(IEnumerable<MyAbstractClass> param1)
受保护的void Foo(IEnumerable参数1)
…然后它会变得更复杂,您需要在C#泛型中进行研究。框架无法知道您需要哪种具体的实现,也不会承担此类决策的责任。这里有两种可能性:
如果您有权访问控制器,是否可以添加另一个继承抽象类而不指定任何成员的类,并使用该类序列化反序列化,然后将其基返回到另一层
我知道这不是一个好的实践,但是有些黑客攻击,但是我不知道抽象类是否可以以某种方式序列化。更新:示例现在使用了一个AJAX JSON帖子 如果必须使用抽象类型,则可以提供用于创建具体实例的。示例如下所示: 模型/模型活页夹
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);
}
protected void Application_Start()
{
...
ModelBinders.Binders.Add(new KeyValuePair<Type, IModelBinder>(typeof(Student), new StudentBinder()));
}
查看
@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>
@model AbstractTest.Models.Student
@使用(Html.BeginForm())
{
Age@Html.TextBoxFor(m=>m.Age)
Name@Html.TextBoxFor(m=>m.Name)
}
$('document').ready(函数(){
$('input#Save')。单击(函数(){
$.ajax({
url:“@Ajax.JavaScriptStringEncode(url.Action(“Index”))”,
键入:“POST”,
数据:GetStudentJsonData($('div#StudentEditor')),
contentType:'application/json;charset=utf-8',
成功:函数(数据、状态、jqxhr){window.location.href='@Url.Action(“Index”);}
});
});
});
var GetStudentJsonData=函数($container){
返回JSON.stringify({
'Age':$container.find('input#Age').attr('value'),
'Name':$container.find('input#Name').attr('value'))
});
};
添加到Global.asax.cs
public ActionResult Index()
{
return View(new GoodStudent { Age = 13, Name = "John Smith" });
}
[HttpPost]
public ActionResult Index(Student student)
{
return View(student);
}
protected void Application_Start()
{
...
ModelBinders.Binders.Add(new KeyValuePair<Type, IModelBinder>(typeof(Student), new StudentBinder()));
}
受保护的无效应用程序\u Start()
{
...
添加(新的键值对(typeof(Student),newstudentbinder());
}
我认为参数必须是一个具体类型。不允许使用抽象类型或接口类型。这些对象来自应用程序中的另一层,它们几乎都是给我的。我对他们没有任何权力。所以,我想我应该创建自己的对象,然后用自己的数据填充抽象对象:(@Dimskiy-你可以从抽象对象继承你的类。正是我所想的,所以我或多或少写了一个重复的答案,但是+1:)我实际上有一个列表,是的,我确实可以访问C#,但只在我的MVC项目内部。我不能触摸业务/DAL层。@Dimskiy-在这种情况下,您可能仍然能够传入一个列表
,其中填充了ThatDerivedClass
对象。如果方法允许协方差,您可以传入列表
,但我不确定。如果您可以编写一个C#包装器来捕获JSON数据,并在将其发送到您的业务/DAL层之前对其进行重新打包,那就太好了。无论谁否决了这一点,请解释原因。我已经阅读并重新阅读了它,我看不出它有什么不正确的原因。这很好,帮助我解决了一个难题。感谢您建议ModelBinders.Binders.Add-in应用程序_Start()。