0

I want to send the email (string) from aspnet/identity to my dbcontext on registration. The console outputs

Failed to load resource. the server responded with a status of 415 () :5001/api/UserEntities/insertEmail:1

When I click on the part in italics I get:

{"type":"https://tools.ietf.org/html/rfc7231#section-6.5.13","title":"Unsupported Media Type","status":415,"traceId":"00-30216fe89ca6b54e8fa1121b1954ad81-0a607d94a5b71142-00"}

RegisterConfirmation.cshtml

    var data = {
            email: $('#email').val()
        };
    $(document).ready(function () {
        $.ajax({
            type: "POST",
            url: '../../api/UserEntities/insertEmail',
            data: data,
            success: function () {
                alert($('#email').val()); //this shows the email correctly in the popup
            }
        });
    });

UserEntitiesController.cs


    [Route("insertEmail")]
    public void Insert([FromBody] string email)
    {
        _uecontext.Users.Add(new DinderDL.Models.UserEntity
        {
            Email = email
        });
        _uecontext.SaveChanges();
    }

I have also tried this with the same result:


    $(document).ready(function () {
        $.post('../../api/UserEntities/insertEmail', {
            email: $('#email').val();
        }).then(alert('hello'));
    });

except I get:

POST https://localhost:5001/api/UserEntities/insertEmail 415
send @ jquery.min.js:2
ajax @ jquery.min.js:2
S.<computed> @ jquery.min.js:2
(anonymous) @ RegisterConfirmation?email=baba@gmail.com&returnUrl=%2F:71
e @ jquery.min.js:2
t @ jquery.min.js:2
setTimeout (async)
(anonymous) @ jquery.min.js:2
c @ jquery.min.js:2
fireWith @ jquery.min.js:2
fire @ jquery.min.js:2
c @ jquery.min.js:2
fireWith @ jquery.min.js:2
ready @ jquery.min.js:2
B @ jquery.min.js:2

2 Answers2

0

Your api endpoint accepts a request with valid request body (determined by [FromBody] decorated on the input string email) but your request is posted with the default contentType of application/x-www-form-urlencoded (by $.ajax). That results in an empty request body sent.

So you have 2 options, either remove the [FromBody] or post the ajax request with a content type of application/json. With that content type, the whole string passed to data option will be sent via the request body. The server-side code will parse that request body using a json serializer formatter (input formatter) because the content-type header value is application/json.

Here is the how you follow the second option (posting json request):

$.ajax({
        type: "POST",
        url: '../../api/UserEntities/insertEmail',
        contentType: 'application/json',
        data: data.email,
        success: function () {
           //...
        }
    });

NOTE: the above code we don't use JSON.stringify because it's unnecessary. Your server-side model is just a string. In case of using JSON.stringify, you need to update your model to use a class like this:

//just an example to help you understand
public class DataModel {
    [JsonProperty("email")]
    public string Email {get;set;}
}
//update your Insert method to this
public void Insert([FromBody] DataModel data)
{
    //accessing data.Email
}
//then you can use JSON.stringify to post the json of your email object
$.ajax({
        type: "POST",
        url: '../../api/UserEntities/insertEmail',
        contentType: 'application/json',
        data: JSON.stringify(data),
        success: function () {
           //...
        }
    });

References:

FromBodyAttribute

Input formatters

King King
  • 61,710
  • 16
  • 105
  • 130
  • Ok so trying both (not being sure on what counts as server side code, is my controller supposed to have a json serializer?) removed the 415, but I'm getting nulls in my database table and the `Console.WriteLine(email)` in my controller shows up empty. – hedonicadapter Jan 09 '21 at 18:38
  • @SamBa there is always a default json serializer supported. It should parse the posted value fine. Have you tried debugging to see if you get a value for `email` posted? Set a break point right at the very beginning of your `Insert` method. If you see it, it works. The next code may cause another issue due to your saving logic, ... (but it should not be asked in this same question). – King King Jan 09 '21 at 18:41
  • @SamBa see my update, it's because your `email` is just a pure string, not a complex model. – King King Jan 09 '21 at 18:44
  • Oh my god it works, thank you so much. My brain is fried right now, I'll come back and try to understand how to use this properly in a bit – hedonicadapter Jan 09 '21 at 18:58
  • you're welcome. My answer explains it fairly well, just read it thoroughly, it has reference links as well. This is all about the so-called `model binding` in asp.net core. – King King Jan 09 '21 at 18:59
0

You Just need to change in your code:

var data = {
            email: $('#email').val()
           };

    $(document).ready(function () {
        $.ajax({
            type: "POST",
            url:'../../api/UserEntities/insertEmail',
            contentType: 'application/json',
            data:  JSON.stringify(data),
            success: function (result) {
               console.log(result);
            }
        });
    });