Search code examples
asp.net-core-mvcremote-validation

Remote validation on file input in .NET Core MVC


I have implemented remote validation on a text property without issue, and the remote validation fires correctly, however I am trying to also add validation for an image upload before the form is submitted. Ideally I would like the file to be validated remotely after selecting the local file. Is there any way to get this working? I cannot see what event actually triggers the remote validation, but I guess it is something that isn't fired in an input element for a file. Any suggestions? Thanks

Have tried the following:

ViewModel:

[Remote(action: "ValidatePhoto", controller: "Photos", ErrorMessage = "Photo width and height must be at least 300 pixels")]
public IFormFile Photo { get; set; }

PhotosController:

public IActionResult ValidatePhoto(IFormFile Photo)
{
    if (Validation.MeetsMinimumImageDimensions(Photo))
    {
        return Json(true);
    }
    return Json(false);
}

View:

<input id="photoUpload" asp-for="Photo" type="file" accept="image/*" name="Photo" style="display:none" />
<span id="submitError" asp-validation-for="Photo" class="text-danger"></span>

Solution

  • For built-in Remote valition, it will Get or Post methods to send request with content in fields. It will not submit file object with form-data.

    Try to implment your own ajax request to back-end method. like below:

        @section Scripts {
            @{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
    
            <script type="text/javascript">
                $(document).ready(function () {
                    document.querySelector("form input[type=file]").onchange = function (event) {
                        var path = $(this).attr("data-val-remote-url");
                        var field = $(this).attr("id");
                        var errormsg = $(this).attr("data-val-remote");
                        var formdata = new FormData();
                        var file = document.getElementById(field).files[0];
                        formdata.append(field, file)
                        $.ajax({
                            url: path,
                            type: 'POST',
                            data: formdata,
                            processData: false,
                            contentType: false,
                            success: function (data) {
                                if (data == false) {
                                    var msg = $("[data-valmsg-for=" + field + "]").first();
                                    msg.html(errormsg)
                                }
                            }
                        });
                        return false;
                    };
                });
            </script>
        }
    

    With this method, it will send two requests to the action with Get method for built-in validation and Post method for our custom request, try change your validation method like

        public IActionResult ValidatePhoto(IFormFile Photo)
        {
            if (Request.Method == HttpMethods.Get)
            {
                return Json(true);
            }
            if (Validation.MeetsMinimumImageDimensions(Photo))
            {
                return Json(true);
            }
            return Json(false);
        }