簡體   English   中英

ASP.Net Core 3.1 - 使用視圖模型上傳文件始終為 NULL

[英]ASP.Net Core 3.1 - File Upload With View Model gets always NULL

我正在嘗試使用視圖模型將文件上傳到服務器。

我的模型是這樣的:

using Microsoft.AspNetCore.Identity;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;

namespace XmlSigner.Data.Models
{
    public class XmlFile : BaseModel
    {
        [IgnoreDataMember]
        [ConcurrencyCheck]  //2 file should not be same
        [Column("FileContent", TypeName = "text"), Required(ErrorMessage = "File Content should be given"), MinLength(5), Display(Name = "File Content", Prompt = "Please Give File Content")]
        public string FileLocationInServer { get; set; }

        [Column("PreviousFileId"), Display(Name = "Previous Signed/Unsigned File", Prompt = "Please select Previous File")]
        public long? PreviousFileId { get; set; }
        [ForeignKey("PreviousFileId"), Display(Name = "Previous Signed/Unsigned File", Prompt = "Please Select Previous File")]
        public virtual XmlFile PreviousSignedFile { get; set; }
    }
}

我的視圖模型是這樣的:

using Microsoft.AspNetCore.Http;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using XmlSigner.Data.Models;

namespace XmlSigner.ViewModels
{
    public class XmlFileAddViewModel
    {
        [Required(ErrorMessage = "File Content should be given"), MinLength(5), Display(Name = "File Content", Prompt = "Please Give File Content")]
        public FormFile XmlFile { get; set; }

        [Display(Name = "Previous Signed/Unsigned File", Prompt = "Please select Previous File")]
        public long? PreviousFileId { get; set; }

        [ForeignKey("PreviousFileId"), Display(Name = "Previous Signed/Unsigned File", Prompt = "Please Select Previous File")]
        public virtual XmlFile PreviousSignedFile { get; set; }
    }
}

而View Form是這樣的:

<form asp-action="Create" enctype="multipart/form-data">
    <div asp-validation-summary="ModelOnly" class="text-danger"></div>
    <div class="form-group">
        <label asp-for="XmlFile" class="control-label"></label>
        <input class="form-control" asp-for="XmlFile">
        <span asp-validation-for="XmlFile" class="text-danger"></span>
    </div>
    <div class="form-group">
        <label asp-for="PreviousFileId" class="control-label"></label>
        <select asp-for="PreviousFileId" class="form-control" asp-items="ViewBag.PreviousFileId"></select>
    </div>

    <div class="form-group">
        <input type="submit" value="Create" class="btn btn-primary" />
    </div>
</form>

而控制器是這樣的:

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(XmlFileAddViewModel xmlFileAddViewModel)
{
    .........................
    .........................
}

我發現的是:

在此處輸入圖片說明

所以,我得到的是上傳的文件為空。

誰能幫我找出為什么我上傳的文件為空?

更新:

如果我使用IFormFile那么我會收到這個錯誤 -

  System.InvalidCastException: The field of type Microsoft.AspNetCore.Http.FormFile must be a string, array or ICollection type.
        at System.ComponentModel.DataAnnotations.MinLengthAttribute.IsValid(Object value)
        at System.ComponentModel.DataAnnotations.ValidationAttribute.IsValid(Object value, ValidationContext validationContext)
        at System.ComponentModel.DataAnnotations.ValidationAttribute.GetValidationResult(Object value, ValidationContext validationContext)
        at Microsoft.AspNetCore.Mvc.DataAnnotations.DataAnnotationsModelValidator.Validate(ModelValidationContext validationContext)
        at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.ValidateNode()
        at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy)
        at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata metadata, String key, Object model)
        at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitChildren(IValidationStrategy strategy)
        at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.VisitComplexType(IValidationStrategy defaultStrategy)
        at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Visit(ModelMetadata metadata, String key, Object model)
        at Microsoft.AspNetCore.Mvc.ModelBinding.Validation.ValidationVisitor.Validate(ModelMetadata metadata, String key, Object model, Boolean alwaysValidateAtTopLevel)
        at Microsoft.AspNetCore.Mvc.ModelBinding.ObjectModelValidator.Validate(ActionContext actionContext, ValidationStateDictionary validationState, String prefix, Object model, ModelMetadata metadata)
        at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.EnforceBindRequiredAndValidate(ObjectModelValidator baseObjectValidator, ActionContext actionContext, ParameterDescriptor parameter, ModelMetadata metadata, ModelBindingContext modelBindingContext, ModelBindingResult modelBindingResult)
        at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value)
        at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
              at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
              at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|24_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
              at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
              at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
              at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
        --- End of stack trace from previous location where exception was thrown ---
              at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
              at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
              at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
              at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
              at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext context)
              at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
              at Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext)
              at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

正如@CodeCaster 所說, MinLengthAttribute用於指定屬性中允許的數組或字符串數​​據的最小長度。因此您不能為IFormFile聲明。

更改如下:

public class XmlFileAddViewModel
{
    [Required(ErrorMessage = "File Content should be given"),Display(Name = "File Content", Prompt = "Please Give File Content")]
    public IFormFile XmlFile { get; set; }

    [Display(Name = "Previous Signed/Unsigned File", Prompt = "Please select Previous File")]
    public long? PreviousFileId { get; set; }
}

參考: MinLengthAttribute 類

嘗試使用IFormFile而不是FormFile如下:

public class XmlFileAddViewModel
{
    [Required(ErrorMessage = "File Content should be given"), MinLength(5), Display(Name = "File Content", Prompt = "Please Give File Content")]
    public IFormFile XmlFile { get; set; }

    [Display(Name = "Previous Signed/Unsigned File", Prompt = "Please select Previous File")]
    public long? PreviousFileId { get; set; }

    [Display(Name = "Previous Signed/Unsigned File", Prompt = "Please Select Previous File")]
    public IFormFile PreviousSignedFile { get; set; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM