C# 抽象模型的Asp.NETCore2.0(MVC)内容绑定器
我刚刚开始用MVC框架开发ASP.Net Core 2.0 当从查看页面发布(表单提交)数据时,我遇到了一些问题 以下是我的观点:C# 抽象模型的Asp.NETCore2.0(MVC)内容绑定器,c#,asp.net-mvc,asp.net-core-mvc,C#,Asp.net Mvc,Asp.net Core Mvc,我刚刚开始用MVC框架开发ASP.Net Core 2.0 当从查看页面发布(表单提交)数据时,我遇到了一些问题 以下是我的观点: <form action="/Media/CreateVideo" method="post"> <input type="text" name="Name" /> <input type="hidden" name="ModelType" value="VideoMode
<form action="/Media/CreateVideo" method="post">
<input type="text" name="Name" />
<input type="hidden" name="ModelType" value="VideoModel" />
<input type="text" name="ContentType" value="video" />
<button type="submit">Yes</button>
</form>
public abstract class ContentModel
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string ContentType { get; set; }
public string Data { get; set; }
public virtual FolderModel ParentFolder { get; set; }
}
public abstract class FileModel : ContentModel
{
public string Path { get; set; }
}
public class VideoModel : FileModel
{
//Other properties i.e. video duration, size, format etc.
}
public class ImageModel : FileModel
{
//Other properties i.e. size, format, cropping value, hue, etc.
}
[HttpPost]
public IActionResult CreateWeb([ModelBinder(BinderType = typeof(CustomModelBinder))]ContentModel item)
{
_contentService.Add(item);
_contentService.SaveChanges();
return View();
}
public class CustomModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
ValueProviderResult values = bindingContext.ValueProvider.GetValue("ModelType");
if (values.Length == 0)
return Task.CompletedTask;
string typeString = values.FirstValue;
Type type = Type.GetType(
"Magic.Core.Models." + typeString + ", Magic.Core.Models",
true
);
object model = Activator.CreateInstance(type);
var metadataProvider = (IModelMetadataProvider)bindingContext.HttpContext.RequestServices.GetService(typeof(IModelMetadataProvider));
bindingContext.ModelMetadata = metadataProvider.GetMetadataForType(type);
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
我的控制器:
<form action="/Media/CreateVideo" method="post">
<input type="text" name="Name" />
<input type="hidden" name="ModelType" value="VideoModel" />
<input type="text" name="ContentType" value="video" />
<button type="submit">Yes</button>
</form>
public abstract class ContentModel
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string ContentType { get; set; }
public string Data { get; set; }
public virtual FolderModel ParentFolder { get; set; }
}
public abstract class FileModel : ContentModel
{
public string Path { get; set; }
}
public class VideoModel : FileModel
{
//Other properties i.e. video duration, size, format etc.
}
public class ImageModel : FileModel
{
//Other properties i.e. size, format, cropping value, hue, etc.
}
[HttpPost]
public IActionResult CreateWeb([ModelBinder(BinderType = typeof(CustomModelBinder))]ContentModel item)
{
_contentService.Add(item);
_contentService.SaveChanges();
return View();
}
public class CustomModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
ValueProviderResult values = bindingContext.ValueProvider.GetValue("ModelType");
if (values.Length == 0)
return Task.CompletedTask;
string typeString = values.FirstValue;
Type type = Type.GetType(
"Magic.Core.Models." + typeString + ", Magic.Core.Models",
true
);
object model = Activator.CreateInstance(type);
var metadataProvider = (IModelMetadataProvider)bindingContext.HttpContext.RequestServices.GetService(typeof(IModelMetadataProvider));
bindingContext.ModelMetadata = metadataProvider.GetMetadataForType(type);
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
我的自定义模型活页夹类:
<form action="/Media/CreateVideo" method="post">
<input type="text" name="Name" />
<input type="hidden" name="ModelType" value="VideoModel" />
<input type="text" name="ContentType" value="video" />
<button type="submit">Yes</button>
</form>
public abstract class ContentModel
{
[Key]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string ContentType { get; set; }
public string Data { get; set; }
public virtual FolderModel ParentFolder { get; set; }
}
public abstract class FileModel : ContentModel
{
public string Path { get; set; }
}
public class VideoModel : FileModel
{
//Other properties i.e. video duration, size, format etc.
}
public class ImageModel : FileModel
{
//Other properties i.e. size, format, cropping value, hue, etc.
}
[HttpPost]
public IActionResult CreateWeb([ModelBinder(BinderType = typeof(CustomModelBinder))]ContentModel item)
{
_contentService.Add(item);
_contentService.SaveChanges();
return View();
}
public class CustomModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
ValueProviderResult values = bindingContext.ValueProvider.GetValue("ModelType");
if (values.Length == 0)
return Task.CompletedTask;
string typeString = values.FirstValue;
Type type = Type.GetType(
"Magic.Core.Models." + typeString + ", Magic.Core.Models",
true
);
object model = Activator.CreateInstance(type);
var metadataProvider = (IModelMetadataProvider)bindingContext.HttpContext.RequestServices.GetService(typeof(IModelMetadataProvider));
bindingContext.ModelMetadata = metadataProvider.GetMetadataForType(type);
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
下面是发生的情况
我能够告诉控制器,这个内容模型是视频模型。
但是,所有post值(如名称、ContentType等)均为空
我曾经在MVC5中按照这个线程来做这件事
而且效果很好
我的问题是,.Net核心中是否遗漏了一些与模型绑定相关的步骤或有什么新内容?好吧,我想您的
CustomModelBinder
需要更多的逻辑来从提供者处获取表单值:
public class CustomModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
ValueProviderResult values = bindingContext.ValueProvider.GetValue("ModelType");
if (values.Length == 0)
return Task.CompletedTask;
string typeString = values.FirstValue;
Type type = Type.GetType(
"Magic.Core.Models." + typeString + ", Magic.Core.Models",
true
);
object model = Activator.CreateInstance(type);
//*get form values from provider
var content = model as ContentModel;
if(content != null)
{
var provider = bindingContext.ValueProvider;
var contentType = provider.GetValue("ContentType");
content.ContentType = contentType != null ? contentType.ToString() : string.Empty;
var name = provider.GetValue("Name");
content.Name = name != null ? name.ToString() : string.Empty;
}
//*/
var metadataProvider = (IModelMetadataProvider)bindingContext.HttpContext.RequestServices.GetService(typeof(IModelMetadataProvider));
bindingContext.ModelMetadata = metadataProvider.GetMetadataForType(type);
bindingContext.Result = ModelBindingResult.Success(model);
return Task.CompletedTask;
}
}
我仍然想知道为什么我必须自己绑定post数据。但在MVC5中,它会自动为我做这件事吗?@DemonEden,你可能在回忆ASP NET(无核心)MVC的
DefaultModelBinder
?是的,DefaultModelBinder及其CreateModel方法。但现在,我最终做了类似于PropertyInfo[]infoList=type.GetProperties()的事情;var provider=bindingContext.ValueProvider;foreach(PropertyInfo info in infoList){var val=provider.GetValue(info.Name).FirstValue;info.SetValue(model,val,null);}由于对性能的影响,需要考虑使用反射。