Search code examples
c#asp.net-mvcasp.net-corerazor-pagesvalidationattribute

C# Razor page required attribute on IFormFile works only when clicking away


The goal here is to get input="file" Required validation attribute to work before clicking away. Now when I select file to upload I have to click away for require validation to work. In result I have to double click submit.

index.cshtml.cs

  [Required(ErrorMessage = "File is required.")]
  [BindProperty]
  [Display(Name = "File")]
  public IFormFile Upload { get; set; }

index.cs

@page
@model IndexModel
@{

   ViewData["Title"] = "Data uploader";
}

@if (Model.Success)
{
   <div class="alert alert-success alert-dismissible">
       <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
       Failas įkeltas.
   </div>
}
@if (Model.Error)
{
   <div class="alert alert-danger alert-dismissible">
       <a href="#" class="close" data-dismiss="alert" aria-label="close">×</a>
       @Model.ErrorMessage
   </div>
}
<div class="panel-body py-4 bg-light">
   <div class="container col-lg-8 floated_elements">
       <div class="h4 text-center py-3">Data update</div>
       <form method="post" class="needs-validation" enctype="multipart/form-data" novalidate>
           <div class="form-group row mb-3">
               <label asp-for="Upload" class="col-sm-2 col-form-label"></label>
               <div class="col-sm-10">
                   <div class="custom-file">
                       <input type="file" asp-for="Upload" class="custom-file-input" accept=".zip" />
                       <label class="custom-file-label">Select file</label>
                       <span asp-validation-for="Upload"></span>
                   </div>
               </div>
           </div>
           <button class="btn btn-primary float-right" type="submit">Submit</button>
       </form>
   </div>
</div>

@section Scripts {

   @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
   <script>
       $(document).ready(function () {
           if ($(".custom-file span").hasClass('field-validation-error')) {
               if (!$(".custom-file-input").hasClass('is-invalid')) {
                   $(".custom-file-input").addClass("is-invalid")
               }
           }
       }
       );
       window.setTimeout(function () {
           $(".alert-success").fadeTo(500, 0).slideUp(500, function () {
               $(this).remove();
           });
       }, 2000);

       $(document).ready(function () {
           $('.custom-file-input').on("change", function () {
               var fileName = $(this).val().split("\\").pop();
               $(this).next('.custom-file-label').html(fileName);
           });
       });

   </script>

}

Solution

  • enter image description here

    Clicking button without populating any of the fields violates the [Required] attributes on the model. The ModelState is invalid. The validation error messages are displayed to view. If you not submit, the validation will not work.

    • Solution 1

    Creat client-side JavaScript Form Validation.

    • Solution 2

    There is a simply solution for you case. Add $("#update").click(); to trigger validation.

    Codes of Js

    <script>
            $(document).ready(function () {
    
                $("#update").click();
    
                if ($(".custom-file span").hasClass('field-validation-error')) {
                    if (!$(".custom-file-input").hasClass('is-invalid')) {
                        $(".custom-file-input").addClass("is-invalid")
                    }
                } 
            }
    

    To have a better user experience, I optimized the code of input change event.

                $('.custom-file-input').on("change", function () {
                    var fileName = $(this).val().split("\\").pop();
                    $(this).next('.custom-file-label').html(fileName);
                    $(".custom-file-input").removeClass("is-invalid");
                    if (fileName == '')
                        $(".custom-file-input").addClass("is-invalid")
                });