模型绑定与继承ASP MVC 5
本文关键字:MVC ASP 继承 绑定 模型 | 更新日期: 2023-09-27 18:02:21
基类:AbstractBuildBlock,派生:TextBlock,ImageBlock,EmptyBlock。
这里的区块:网站->页面[someIndex]->行[someIndek]->BuildBlocks
FieldsBuildBlocks的类型是AbstractBuildBlock,所以当我在BuildBlocks中将Site保存到DB时,每条记录都有描述符AbstractBuildingBlock。我尝试在BuildBlockRepository中做下一步:
switch(obj.ContentType)
{
case "text":
obj = obj as TextBlock;
context.BuildBlocks.Add(obj);
break;
}
在obj = obj as TextBlock
之后,obj
是null
。原因是obj的类型是AbstractBuildBlock。我在msdn发现这个代码应该可以工作:
BaseClass a = new DerivedClass()
DerivedClass b = a as DerivedClass
所以我需要在模型绑定时复制这个代码。这是ajax请求:
$('.saveSite').click(function () {
$.ajax({
url: '/Site/Update',
data: { site: getSite() },
method: 'POST',
success: function (data) {
console.log('Success save');
},
error: function (data) {
debugBox(data);
}
});
});
和此请求的mvc操作
public string Update(Site site)
{
siteRepository.Add(site);
return "Success";
}
所以我以json形式发送Site,这个站点中的BuildBlock也以json的形式发送,但它们的(块(类型当然不是AbstractBuildBlock,它们都是TextBlock、ImageBlock等,并且有带值的字段。
问题:站点有类型为AbstractBuildBlock的字段BuildBlocks,模型绑定器做如下操作:
buildBlock = new AbstractBuildBlock(); //loose derived classes fields and posibility to convert it in DerivedClass
buildBlocks.push(buildBlock)
但我需要像这样的东西
switch(buildBlock.contenType) {
case "text" : buildBlock = new TextBlock();buidlBlocks.push(buildBlock);
}
JSON NET自定义反序列化程序在上无法工作
ASP MVC 5如何借助JSON NET 从请求中读取对象
看看上面两个链接中的答案,正确的ajax调用描述为
下面的服务器代码
mvc动作
public string Update(Site site)
{
TextBlock block = site.Pages[0].Rows[0].BuildBlocks[0] as TextBlock;
siteRepository.Add(site);
return "Success";
}
AbstractJsonCreationConverter我已经在基础设施文件夹中创建了它
public abstract class AbstractJsonCreationConverter<T> : JsonConverter
{
protected abstract T Create(Type objectType, JObject jsonObject);
public override bool CanConvert(Type objectType)
{
return typeof(T).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
var jsonObject = JObject.Load(reader);
var target = Create(objectType, jsonObject);
serializer.Populate(jsonObject.CreateReader(), target);
return target;
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
在同一文件夹中的混凝土类
public class JsonBuildBlockConverter : AbstractJsonCreationConverter<AbstractBuildBlock>
{
protected override AbstractBuildBlock Create(Type objectType, JObject jsonObject)
{
var type = jsonObject["contentType"].ToString();
switch(type)
{
case "text":
return new TextBlock();
default:
return null;
}
}
}
以及基础设施中的另一个类别
internal class SiteModelBinder : System.Web.Mvc.IModelBinder
{
public object BindModel(ControllerContext controllerContext, System.Web.Mvc.ModelBindingContext bindingContext)
{
// use Json.NET to deserialize the incoming Position
controllerContext.HttpContext.Request.InputStream.Position = 0; // see: https://stackoverflow.com/a/3468653/331281
Stream stream = controllerContext.RequestContext.HttpContext.Request.InputStream;
var readStream = new StreamReader(stream, Encoding.UTF8);
string json = readStream.ReadToEnd();
return JsonConvert.DeserializeObject<Site>(json, new JsonBuildBlockConverter());
}
}
最后一个类是ModelBinder,它将被调用来解析Site类型的变量,要使其工作,您需要在ApplicationStart((中的Global.asax.cs中注册它
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
ModelBinders.Binders.Add(typeof(Site), new SiteModelBinder()); //RegisterModelBinder for Site
}
这就是全部。