skip to Main Content

Now before you mark this as a duplicate, I have read other threads (Multipart body length limit exceeded exception). But no answers have worked so far.

So in my .NET 6 API I am expecting a form. The endpoint looks as follows:

   [HttpPost]
    public async Task<IActionResult> Post([FromForm] PostUploadDto post)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var author = userService.GetUser(post.Author);

    var newPost = new Post
    {
        AuthorId = author.Id,
        Description = post.Description,
        Posted = post.Posted,
        RatingNegative = 0,
        RatingPositive = 0,
        Title = post.Title,
    };

    await postService.CreatePost(newPost);

    try
    {

        foreach (var file in post.Files)
        {
            var fileName = $"{newPost.Id}_{file.FileName}";
            var filePath = Path.Combine("path", fileName);

            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await file.CopyToAsync(stream);
            }

            var uploadDate = DateTime.Now;

            await postService.AddPostFile(new PostFile
            {
                PostId = newPost.Id,
                Path = filePath,
                Name = fileName,
                Uploaded = uploadDate
            });
        }

        return Ok(newPost.Id);
    }
    catch (Exception ex)
    {
        return BadRequest(new { message = ex.Message, innerMessage = ex.InnerException?.Message });
    }
}

here I expect a form which will be constructed in a React TS application. This application is pretty simple: on a submit formdata will be created and sent to the endpoint above. The code which is used to compose form data can be seen below:

const [title, setTitle] = useState('')
const [description, setDescription] = useState('')
const [selectedFiles, setSelectedFiles] = useState<File[]>([])

const getFormData = () => {
    const formData = new FormData()

    formData.append('title', title)
    formData.append('description', description)

    if (user) {
        formData.append('author', user.id.toString())
    }

    formData.append('posted', new Date().toDateString())
    selectedFiles.forEach((file, index) => {
        formData.append('files', file);
    });

    return formData
}

const handleSubmit = (e: any) => {
    e.preventDefault()

    if (user && authorisationToken) {
        const data = getFormData()

        apiService.post<Post>(`https://host/api/posts`, data, authorisationToken, true).then((response) => {
            setPosts([...posts, response.data])
            setTitle('')
            setDescription('')
            setSelectedFiles([])
            setIsModalOpen(false)
        })
            .catch((error) => {
                console.error('API error:', error)
            })
    }
}

This data will be received by an endpoint. The apiService uses standard fetch from React. The apiService looks like follows (relevant code):

async function request<T>(url: string, method: string, data?: any, token?: string, isForm = false): Promise<ApiResponse<T>> {
    let contentType = 'application/json'
    let bodyData = data ? JSON.stringify(data) : undefined

    if (isForm) {
        contentType = `multipart/form-data; boundary=---------------------------${Date.now().toString(16)}`
        bodyData = data
    }

    const headers: HeadersInit = {
        'Content-Type': contentType,
    };

    if (token) {
        headers['Authorization'] = `Bearer ${token}`;
    }

    const response = await fetch(url, {
        method,
        headers,
        body: bodyData,
    });

    const responseData: T = await response.json();

    return {
        data: responseData,
        status: response.status,
    };
}

const apiService = {
    ...

    post<T>(url: string, data: any, token ?: string, isForm = false): Promise<ApiResponse< T >> {
        return request<T>(url, 'POST', data, token, isForm);
    },

    ...
}

The request is being sent properly to the right endpoint, nothing goes wrong here. It only goes wrong with the formdata validation of my API which is hosted on IIS (Windows 11 server). I never had issues with this before until now. I know that this might seem as a duplicate but I have changed my configuration based on existing threads and I am still struggling with this issue. As proof here is a code snippet from my program.cs:

builder.Services.Configure<FormOptions>(x =>
{
    x.ValueLengthLimit = int.MaxValue;
    x.MultipartBodyLengthLimit = int.MaxValue;
});

Are there any steps I might have overlooked, does anybody have a suggestion, do I need to provide more info?

POSTMAN request (working)

In postman I have a request which I got off my swagger. This request works fine and uploads files just fine too. The headers for the request can be seen below

Postman posts request

2

Answers


  1. this parameters will solve your error

    make sure to set them in your .config file

    <configuration>
      <system.web>
        <httpRuntime maxRequestLength="1048576" />
      </system.web>
      <system.webServer>
        <security>
          <requestFiltering>
            <requestLimits maxAllowedContentLength="1073741824" /> <!-- 1 GB -->
          </requestFiltering>
        </security>
      </system.webServer>
    </configuration>
    
    Login or Signup to reply.
  2. It could be that you either have to decorate your class where the endpoint is being called with the following code:

    [RequestFormLimits(ValueCountLimit = 2500)]  //Add your limit
    

    And/Or add the following option to your FormOptions in the Program.cs class

    builder.Services.Configure<FormOptions>(x => {
        x.ValueCountLimit = int.MaxValue;
    });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search