Diretório de artigos
Prefácio
No ASP.NET MVC, a vinculação de modelo de dados é o processo de conversão de dados de solicitação HTTP (como dados de formulário) em objetos CLR. Os modelos de vinculação personalizados nos permitem controlar a vinculação do modelo de dados por meio de regras personalizadas. Aqui estão alguns exemplos de modelos de vinculação personalizados:
-
Fichário de modelo personalizado: podemos implementar nosso próprio fichário de modelo, herdar a interface IModelBinder e substituir o método BindModel para implementar a lógica de ligação personalizada.
-
Usando conversores de atributos: podemos usar conversores de atributos para personalizar o comportamento de conversão de valores. Isso pode ser conseguido adicionando um TypeConverterAttribute à propriedade a ser vinculada.
-
Validador de modelo personalizado: podemos implementar nosso próprio validador de modelo, herdar a interface IModelValidator e substituir o método Validate para implementar regras de validação personalizadas.
-
Provedor de metadados de modelo personalizado: podemos implementar nosso próprio provedor de metadados de modelo, herdar a classe ModelMetadataProvider e substituir os métodos GetMetadataForProperty e GetMetadataForType para implementar regras de metadados personalizados.
-
Provedor de fichário de modelo personalizado: podemos implementar nosso próprio provedor de fichário de modelo, herdar a classe ModelBinderProvider e substituir o método GetBinder para implementar regras de fichário personalizadas.
1. Modelo de vinculação personalizado (upload de arquivo)
1. Vinculação de modelo integrada
No ASP.NET Core MVC, a seguir estão propriedades comuns de associação de parâmetros:
- FromBodyAttribute: desserializa o corpo solicitado em um objeto do tipo especificado. Por exemplo:
[HttpPost]
public IActionResult Create([FromBody]TodoItem item)
{
// code
}
- FromFormAttribute: desserializa os dados do formulário solicitados em um objeto do tipo especificado. Por exemplo:
[HttpPost]
public IActionResult Create([FromForm]TodoItem item)
{
// code
}
- FromQueryAttribute: vincula os parâmetros da string de consulta da solicitação aos parâmetros do método especificado. Por exemplo:
[HttpGet]
public IActionResult Get([FromQuery]string name)
{
// code
}
- FromHeaderAttribute: vincula o valor do cabeçalho da solicitação ao parâmetro do método especificado. Por exemplo:
[HttpGet]
public IActionResult Get([FromHeader]string xMyHeader)
{
// code
}
- FromServicesAttribute: injete o tipo de serviço especificado no controlador ou parâmetro do método. Por exemplo:
public class MyController : Controller
{
private readonly ILogger<MyController> _logger;
public MyController([FromServices]ILogger<MyController> logger)
{
_logger = logger;
}
// code
}
- FromRouteAttribute: vincula parâmetros de rota a parâmetros de método especificados. Por exemplo:
[HttpGet("{id}")]
public IActionResult Get([FromRoute]int id)
{
// code
}
Essas propriedades de associação de parâmetros fornecem uma maneira flexível e concisa de vincular parâmetros de método do controlador, facilitando o tratamento de solicitações HTTP.
2. Vinculação de modelo personalizado
2.1 Personalizar FromFileAttribute
public class FromFileAttribute : Attribute, IBindingSourceMetadata
{
public BindingSource BindingSource => BindingSource.Form;
}
2.2 Classe de recebimento de arquivo personalizado
public class UserFile
{
public string FileName {
get; set; }
public long Length {
get; set; }
public string Extension {
get; set; }
public string FileType {
get; set; }
private readonly static string[] Filters = {
".jpg", ".png", ".bmp" };
public bool IsValid => !string.IsNullOrEmpty(this.Extension) && Filters.Contains(this.Extension);
private IFormFile file;
public IFormFile File
{
get {
return file; }
set
{
if (value != null)
{
this.file = value;
this.FileType = this.file.ContentType;
this.Length = this.file.Length;
this.Extension = this.file.FileName.Substring(file.FileName.LastIndexOf('.'));
if (string.IsNullOrEmpty(this.FileName))
this.FileName = this.FileName;
}
}
}
public async Task<string> SaveAs(string destinationDir = null)
{
if (this.file == null)
throw new ArgumentNullException("没有需要保存的文件");
if (destinationDir != null)
Directory.CreateDirectory(destinationDir);
var newName = DateTime.Now.Ticks;
var newFile = Path.Combine(destinationDir ?? "", $"{
newName}{
this.Extension}");
using (FileStream fs = new FileStream(newFile, FileMode.CreateNew))
{
await this.file.CopyToAsync(fs);
fs.Flush();
}
return newFile;
}
}
2.3 Uso no controlador
[ApiController]
[Route("[controller]")]
public class HomeController : ControllerBase
{
[HttpPost]
public async Task<IActionResult> Post([FromFile] UserFile file)
{
if (file == null || !file.IsValid)
return new JsonResult(new {
code = 500, message = "不允许上传的文件类型" });
string newFile = string.Empty;
if (file != null)
newFile = await file.SaveAs("/data/files/images");
return new JsonResult(new {
code = 0, message = "成功", url = newFile });
}
}
2.4 Teste
Ver pasta do diretório