Posting to web API results in Unsupported Media Type

Clemens Linders 21 Reputation points
2022-07-13T09:42:37.393+00:00

Hi,

I have an application in .Net 6 that contains a asp.net core Web API and a Winform .Net 6 test program to consume the API.
When I perform a Post I always get the error: Unsupported Media Type.

If I use the swagger page and test the Post command than it works just fine.

This is the code from the web API controller:

    [Route("Persons/PostPersons")]  
    [HttpPost]  
    public void PostPersons([FromBody] Persons value)  
    {  
        PersonList.Add(value);  
    }  

This is the entire controller:
namespace WebAPI.Controllers
{

[Route("api/[controller]")]  
[ApiController]  
public class ValuesController : ControllerBase  
{  
    public List<Persons> PersonList = new();  

    // GET: api/<ValuesController>  
    [HttpGet]  
    public IEnumerable<string> Get()  
    {  
        return new string[] { "value1", "value2" };  
    }  

    // GET api/<ValuesController>/5  
    [HttpGet("{id}")]  
    public string Get(int id)  
    {  
        string retVal = "return value";  

        switch (id)  
        {  
            case 1:  
                retVal = "return value: 1";  
                break;  

            case 2:  
                retVal = "return value: 2";  
                break;  

            case 3:  
                retVal = "return value: 3";  
                break;  

            default:  
                break;  
        }  

        return retVal;  
    }  

    //sample for having multiple get commands  
    [Route("Blabla/GetBlabla")]//[Route("/Blabla/GetBlabla/{userId:int}/{age:int}")]//for passing 2 vars  
    [HttpGet]  
    public string GetBlabla()//Blabla/GetBlabla(int userId, int age)//for passing 2 vars ====> calling the getcommand: http://localhost:12345/api/Values/GetBlabla/23/39  
    {  
        return "Blabla";  
    }  

    [Route("Persons/GetPersons")]  
    [HttpGet]  
    public IEnumerable<Persons> GetPersons()  
    {  

        Persons john = new()  
        {  
            FirstName = "John",  
            LastName = "De Vries",  
            ID = "1"  
        };  

        Persons jimmy = new()  
        {  
            FirstName = "Jimmy",  
            LastName = "Van Ver",  
            ID = "2"  
        };  

        PersonList.Add(john);  
        PersonList.Add(jimmy);  
        return PersonList.ToArray();  
    }  

    // POST api/<ValuesController>  
    [HttpPost]  
    public void Post([FromBody] string value)  
    {  
    }  

    [Route("Persons/PostPersons")]  
    [HttpPost]  
    public void PostPersons([FromBody] Persons value)  
    {  
        PersonList.Add(value);  
    }  

    // PUT api/<ValuesController>/5  
    [HttpPut("{id}")]  
    public void Put(int id, [FromBody] string value)  
    {  
    }  

    // DELETE api/<ValuesController>/5  
    [HttpDelete("{id}")]  
    public void Delete(int id)  
    {  
    }  
}  

}

In my WinForm application I have some radio buttons and a testbutton.
So when I select the radio button: PersonsPost the last CASE code becomes activated:

    private async void btnApiTest_Click(object sender, EventArgs e)  
    {  
        switch (SelectedTest)  
        {  
            case SelectedTestEnum.BlablaGet:  
                SelectedController = SelectedControllerEnum.Values;  
                rtbResult.Text = await GetDataFromApi("/Blabla/GetBlabla");  
                break;  
            case SelectedTestEnum.ValuesGet:  
                SelectedController = SelectedControllerEnum.Values;  
                rtbResult.Text = await GetDataFromApi("");  
                break;  
            case SelectedTestEnum.ValuesPlusIDGet:  
                SelectedController = SelectedControllerEnum.Values;  
                rtbResult.Text = await GetDataFromApi("", tbValuesID.Text);  
                break;  
            case SelectedTestEnum.WeatherForecastGet:  
                SelectedController = SelectedControllerEnum.WeatherForecast;  
                rtbResult.Text = await GetDataFromApi("");  
                break;  
            case SelectedTestEnum.PersonsGet:  
                SelectedController = SelectedControllerEnum.Values;  
                rtbResult.Text = await GetDataFromApi("/Persons/GetPersons");  
                break;  
            case SelectedTestEnum.PersonsPost:  
                SelectedController = SelectedControllerEnum.Values;  
                rtbResult.Text = await PostDataToApi("/Persons/PostPersons");  
                break;  
        }  
    }  


    public static async Task<string> PostDataToApi(string urlExtension)  
    {  
        string baseController = BaseUrlValuesController;  

        using (HttpClient client = new())  
        {  
            var formDictionary = new Dictionary<string, string>();  
            formDictionary.Add("FirstName", "John");  
            formDictionary.Add("LastName", "Rock");  
            formDictionary.Add("ID", "JR");  

            var formContent = new FormUrlEncodedContent(formDictionary);  

            client.BaseAddress = new Uri(baseController + urlExtension);  
            client.DefaultRequestHeaders.Accept.Clear();  
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));  
            using HttpResponseMessage res = await client.PostAsync(baseController + urlExtension, formContent);  
            using HttpContent content = res.Content;  
            string data = await content.ReadAsStringAsync();  

            if (data != null)  
            {  
                return PresentReadableJson(data);  
            }  
        }  

        return string.Empty;  
    }  

    public static string PresentReadableJson(string json)  
    {  
        try  
        {  
            JToken parseJson = JToken.Parse(json);  
            return parseJson.ToString(Formatting.Indented);  
        }  
        catch  
        {  
            return json;//This is not json formatted  
        }  
    }  

The baseController + urlExtension is exactly the same as what swagger uses (https://localhost:7233/api/Values/Persons/PostPersons), so I think that is not the problem.

I hope someone can help me, I tried several options, but the problem remains.

If I test the swagger page than (I have a breakpoint at PostPersons) the debugger halts at PostPersons.
However if I perform my own Post command, the debugger doesn't.

This is the swagger page:
220209-afbeelding.png

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,779 questions
0 comments No comments
{count} votes

Accepted answer
  1. AgaveJoe 29,786 Reputation points
    2022-07-13T10:53:24.067+00:00

    Working example.

    Client

        static readonly HttpClient client = new HttpClient();  
        public static async Task Main(string[] passwordargs)  
        {  
            client.BaseAddress = new Uri("https://localhost:7134");  
            Person? responceModel;  
            Person requestModel = new Person()  
            {  
                id = 1,  
                firstname = "Hello",  
                lastname = "World"            
            };  
      
      
            HttpResponseMessage response = await client.PostAsJsonAsync("api/Values/Persons/PostPersons", requestModel);  
            using (var contentStream = await response.Content.ReadAsStreamAsync())  
            {  
                responceModel = await JsonSerializer.DeserializeAsync<Person>(contentStream);  
            }  
      
            Console.WriteLine($"{responceModel?.id}");  
            Console.WriteLine($"{responceModel?.firstname}");  
            Console.WriteLine($"{responceModel?.lastname}");  
        }  
    

    Action

    [Route("Persons/PostPersons")]  
    [HttpPost]  
    public Person PostPersons([FromBody] Person value)  
    {  
        return value;  
    }  
    
    0 comments No comments

1 additional answer

Sort by: Most helpful
  1. Clemens Linders 21 Reputation points
    2022-07-13T12:07:05.65+00:00

    Hi AgaveJoe

    Thanks for your reply, it is was I was looking for.

    Kind regards,

    Clemens Linders

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.