[Yugong Series] September 2023.NET/C# Knowledge Points-Customized Binding Model (File Upload)


Preface

In ASP.NET MVC, data model binding is the process of converting HTTP request data (such as form data) into CLR objects. Custom binding models allow us to control data model binding through custom rules. Here are some examples of custom binding models:

  1. Custom model binder: We can implement our own model binder, inherit the IModelBinder interface, and override the BindModel method to implement custom binding logic.

  2. Using attribute converters: We can use attribute converters to customize the conversion behavior of values. This can be achieved by adding a TypeConverterAttribute to the property to be bound.

  3. Custom model validator: We can implement our own model validator, inherit the IModelValidator interface, and override the Validate method to implement custom validation rules.

  4. Custom model metadata provider: We can implement our own model metadata provider, inherit the ModelMetadataProvider class, and override the GetMetadataForProperty and GetMetadataForType methods to implement custom metadata rules.

  5. Custom model binder provider: We can implement our own model binder provider, inherit the ModelBinderProvider class, and override the GetBinder method to implement custom binder rules.

1. Custom binding model (file upload)

1. Built-in model binding

In ASP.NET Core MVC, the following are common parameter binding properties:

  1. FromBodyAttribute: Deserialize the requested body into an object of the specified type. For example:
[HttpPost]
public IActionResult Create([FromBody]TodoItem item)
{
    
    
    // code
}
  1. FromFormAttribute: Deserialize the requested form-data into an object of the specified type. For example:
[HttpPost]
public IActionResult Create([FromForm]TodoItem item)
{
    
    
    // code
}
  1. FromQueryAttribute: Binds the request's query string parameters to the specified method parameters. For example:
[HttpGet]
public IActionResult Get([FromQuery]string name)
{
    
    
    // code
}
  1. FromHeaderAttribute: Binds the request's header value to the specified method parameter. For example:
[HttpGet]
public IActionResult Get([FromHeader]string xMyHeader)
{
    
    
    // code
}
  1. FromServicesAttribute: Inject the specified service type into the controller or method parameter. For example:
public class MyController : Controller
{
    
    
    private readonly ILogger<MyController> _logger;

    public MyController([FromServices]ILogger<MyController> logger)
    {
    
    
        _logger = logger;
    }

    // code
}
  1. FromRouteAttribute: Bind route parameters to specified method parameters. For example:
[HttpGet("{id}")]
public IActionResult Get([FromRoute]int id)
{
    
    
    // code
}

These parameter binding properties provide a flexible and concise way to bind controller method parameters, making it easier to handle HTTP requests.

2. Custom model binding

2.1 Customize FromFileAttribute

public class FromFileAttribute : Attribute, IBindingSourceMetadata
{
    
    
    public BindingSource BindingSource => BindingSource.Form;
}

Insert image description here

2.2 Custom file receiving class

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;
    }
}

Insert image description here

2.3 Use in controller

[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 });
    }
}

Insert image description here

2.4 Testing

Insert image description here
View directory folder
Insert image description here

Guess you like

Origin blog.csdn.net/aa2528877987/article/details/132875013