skip to Main Content

UPDATE:
Some weird behaviour. If I post to a controller it works and I get files and data. However, if I post to the page itself (Razor code behind) public void OnPost(...) I get the 400 error. It’s almost like the page can’t find itself, which is also weird because other methods on that page OnGet and OnGetData work with no issue.

The error that gets shown in the browser console is here

enter image description here

If you click the links it goes to the page so I know the path is valid.

I put everything on the page so that it’s self-contained and I can reuse the page anywhere, and I don’t have to worry about changes elsewhere breaking that page, nor changes to that page breaking anything else. The pages are data-driven, so configured via a database, I have around 7 or 8 pages (of this type) and they all work just fine, but this is the first of this type that has file upload as part of its functionality.


THE PROBLEM:
I have the following situation. This works perfectly, but when I try to use formData to enable file upload I get a 400 (bad request) error. I have tried all manner of content-type and enctype, but nothing seems to work. Any ideas as to what’s going wrong?

You can see the commented lines. if I switch to those I always get a 400 ‘bad request’

Visual Studio 2022, Net 8.

My Form (BS5 Modal)

<form id="frmItemLocalForm" method="post" name="frmItemLocalForm" novalidate="novalidate" enctype="multipart/form-data">
    @Html.AntiForgeryToken()
    <input type="hidden" name="controlId" id="controlId" value="@ViewData["controlid"]" />
    <input type="hidden" name="itemId" id="itemId" value="@ViewData["itemId"]" />
    <input type="hidden" asp-for="UserDocument.Created" name="Created" />

    <!--Modal Header-->
    <div class="modal-header">
        <h4 class="modal-title">Edit User Document</h4>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
    </div>

    <!-- Modal body -->
    <div class="modal-body">

        <div class="row my-1">
            <label class="col-form-label col-md-2">Name</label>
            <div class="col-md-10">
                <input type="text" class="form-control" placeholder="Name" asp-for="UserDocument.DocumentName" name="DocumentName" data-rule-required="true" />
            </div>
        </div>

        <div class="row my-1">
            <label class="col-form-label col-md-2">File</label>
            <div class="col-md-10">
                <input type="file" class="form-control fileUpload" placeholder="User Document" name="userdocumentfileupload" id="userdocumentfileupload" data-rule-required="true" required />
                <br />@Model.UserDocument?.DocumentName @Model.UserDocument?.FileName
            </div>
        </div>
    </div>

    <!-- Modal footer -->
    <div class="modal-footer">
        <button type="submit" id="editLocalForm" class="btn btn-primary">OK</button>
        <button type="button" class="btn btn-danger close-button" data-bs-dismiss="modal">Close</button>
    </div>
</form>
$(document).on("click", "#editLocalForm", function (e) {
    e.preventDefault();
    e.stopPropagation();

    var myform = $("#frmItemLocalForm");
    var valid = myform.valid();

    if (valid) {

        var formData = new FormData();

        //$(".fileUpload").each(function () {
        //    var fileInput = $(this)[0];
        //    var file = fileInput.files[0];

        //    if (file.size > 0) {
        //        formData.append($(this).attr("id"), file);
        //    }
        //});

        //formData.append("myFormData", myform.serialize());

        $.ajax({
            url: formUrl,
            data: myform.serialize(),//formData,
            dataType: "html",
            contentType: "application/x-www-form-urlencoded",
            processData: false,
            method: "post",
            success: function (result) {
                $(".close-button").click();
                table.ajax.reload(null, false);
            },
            error: function (err) {
                console.log(err);
            }
        });
    }
});

Server End Point.
I have a break point here that doesn’t even get hit

public void OnPost()
{
    ... Request.Form.Files...

}

2

Answers


  1. Have you tried change contentType: "application/x-www-form-urlencoded" to contentType: 'multipart/form-data' or maybe contentType: false?

    With those contentType, you can send myform without serializing it inside the data of your ajax

    Login or Signup to reply.
  2. Razor Pages enable anti-forgery token validation by default, so you need add this token to header in ajax. Otherwise you may receive 400 Bad Request error.

    If you use ajax post the data with file input, it should be:

    contentType: false,
    processData: false,
    

    Also you need use FormData instead of form.serialize().

    A whole working demo:

    Index.cshtml

    @page
    @model IndexModel
    <form id="frmItemLocalForm" method="post" name="frmItemLocalForm" novalidate="novalidate" enctype="multipart/form-data">
        @Html.AntiForgeryToken()
        <input type="hidden" name="controlId" id="controlId" value="1" />
        <input type="hidden" name="itemId" id="itemId" value="2" />
        <input type="hidden" asp-for="UserDocument.Created" name="Created" value="created2" />
    
        <!--Modal Header-->
        <div class="modal-header">
            <h4 class="modal-title">Edit User Document</h4>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        </div>
    
        <!-- Modal body -->
        <div class="modal-body">
    
            <div class="row my-1">
                <label class="col-form-label col-md-2">Name</label>
                <div class="col-md-10">
                    <input type="text" class="form-control" placeholder="Name" asp-for="UserDocument.DocumentName" name="DocumentName" data-rule-required="true" />
                </div>
            </div>
    
            <div class="row my-1">
                <label class="col-form-label col-md-2">File</label>
                <div class="col-md-10">
                    <input type="file" class="form-control fileUpload" placeholder="User Document" name="userdocumentfileupload" id="userdocumentfileupload" data-rule-required="true" required />
                    <br />@Model.UserDocument?.DocumentName @Model.UserDocument?.FileName
                </div>
            </div>
        </div>
    
        <!-- Modal footer -->
        <div class="modal-footer">
            <button type="button" id="editLocalForm" class="btn btn-primary">OK</button>
            <button type="button" class="btn btn-danger close-button" data-bs-dismiss="modal">Close</button>
        </div>
    </form>
    @section Scripts {
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.5/jquery.validate.js" type="text/javascript"></script>
        <script>
                $(document).on("click", "#editLocalForm", function (e) {
                    e.preventDefault();
                    e.stopPropagation();
    
                    var myform = $("#frmItemLocalForm");
                    var valid = myform.valid();
    
                    if (valid) {
    
                        var formData = new FormData();
    
                    formData.append("userdocumentfileupload", $('.fileUpload')[0].files[0]);
                    formData.append("userDocument.Created", $('input[name="Created"]').val());
                    formData.append("userDocument.DocumentName", $('input[name="DocumentName"]').val());
                    formData.forEach(function (value, key) {
                        console.log(key, value);
                    });
                        $.ajax({
                            url: "/Index",
                             data: formData,
                            dataType: "html",
                            contentType: false,
                            processData: false,
                            method: "post",
                        headers: {
                            RequestVerificationToken:
                                $('input:hidden[name="__RequestVerificationToken"]').val()
                        },
                        success: function (result) {
                                $(".close-button").click();
                                //table.ajax.reload(null, false);
                            },
                            error: function (err) {
                                console.log(err);
                            }
                        });
                    }
                });
        </script>
    }
    

    Index.cshtml.cs

    public class IndexModel : PageModel
    {
        public void OnGet()
        {
            
        }
        [BindProperty]
        public UserDocument UserDocument { get; set; }
        public void OnPost(UserDocument userDocument,IFormFile userdocumentfileupload) 
        { 
        }
    }
    public class UserDocument
    {
        public string Created { get; set; }
        public string DocumentName { get; set; }
        public string? FileName { get; set; }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search