Resolving HTTP 415 Unsupported Media Type Errors in ASP.NET Core Form POST Requests

Nov 22, 2025 · Programming · 10 views · 7.8

Keywords: ASP.NET Core | HTTP 415 | FromForm | FromBody | Model Binding

Abstract: This article provides an in-depth analysis of HTTP 415 errors in ASP.NET Core form POST requests, focusing on the differences between [FromBody] and [FromForm] attributes. Through detailed code examples and request header analysis, it explains the root cause of media type mismatches and offers best practices for migrating from traditional ASP.NET MVC to ASP.NET Core. The article also discusses implementing custom model binders to support multiple content types, providing comprehensive solutions for developers.

Problem Background and Error Phenomenon

During ASP.NET Core development, many developers encounter HTTP 415 Unsupported Media Type responses when making form POST requests. This error commonly occurs during migration from traditional ASP.NET MVC to ASP.NET Core due to significant differences in request processing mechanisms.

Core Issue Analysis

The root cause lies in the mismatch between the [FromBody] attribute and the media type of form POST requests. In ASP.NET Core, the [FromBody] attribute expects request body content with application/json content type, while traditional form POST requests use application/x-www-form-urlencoded content type.

Here is the typical controller code that causes the problem:

public class MyController : Controller
{
    [HttpPost]
    public async Task<IActionResult> Submit([FromBody] MyModel model)
    {
        // Processing logic
    }
}

The corresponding HTTP request headers show form-encoded content type:

POST /submit HTTP/1.1
Content-Type: application/x-www-form-urlencoded
...

Solution: Using the Correct Binding Attribute

For form POST requests, the correct solution is to use the [FromForm] attribute instead of [FromBody]:

public class MyController : Controller
{
    [HttpPost]
    public async Task<IActionResult> Submit([FromForm] MyModel model)
    {
        // Processing logic
    }
}

The [FromForm] attribute is specifically designed to handle requests with application/x-www-form-urlencoded content type, properly binding model parameters from form data.

Detailed Attribute Usage Rules

In ASP.NET Core, binding attribute usage follows specific rules:

Alternative Approach: Modifying Request Content Type

If you prefer to continue using the [FromBody] attribute, you can modify the client request's content type:

Content-Type: application/json

This approach requires clients to send JSON-formatted data, which is suitable for API scenarios but not for traditional HTML form submissions.

Advanced Application: Supporting Multiple Content Types

In some scenarios, you may need a single endpoint to support multiple content types. This can be achieved through custom model binders:

public class MultiContentTypeModelBinder : IModelBinder
{
    public async Task BindModelAsync(ModelBindingContext bindingContext)
    {
        var request = bindingContext.HttpContext.Request;
        
        if (request.ContentType == "application/json")
        {
            // Read JSON data from request body
            string body;
            using (var reader = new StreamReader(request.Body))
            {
                body = await reader.ReadToEndAsync();
            }
            var model = JsonConvert.DeserializeObject(body, bindingContext.ModelType);
            bindingContext.Result = ModelBindingResult.Success(model);
        }
        else if (request.ContentType == "application/x-www-form-urlencoded")
        {
            // Bind model from form data
            var model = Activator.CreateInstance(bindingContext.ModelType);
            foreach (var property in bindingContext.ModelType.GetProperties())
            {
                var value = request.Form[property.Name];
                if (!string.IsNullOrEmpty(value))
                {
                    property.SetValue(model, Convert.ChangeType(value, property.PropertyType));
                }
            }
            bindingContext.Result = ModelBindingResult.Success(model);
        }
    }
}

Register the custom model binder in Program.cs:

builder.Services.AddControllers(options =>
{
    options.ModelBinderProviders.Insert(0, new MultiContentTypeModelBinderProvider());
});

Migration Considerations

When migrating from ASP.NET MVC 5 to ASP.NET Core, pay attention to these key differences:

Best Practice Recommendations

Based on practical development experience, follow these best practices:

By understanding ASP.NET Core's model binding mechanism and correctly using binding attributes, developers can effectively avoid HTTP 415 errors and build more robust web applications.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.