0

This is my UI which uses ajax to post data to the web api.

<form id="myForm" method="post">
    Username <input name="Email" id="Email" type="text" /> <br />
    Password <input name="Password" id="Password" type="text" /> <br />
    Confirm Password <input name="ConfirmPassword" id="ConfirmPassword" type="text" /> <br />
    <input id="btnRegister" type="submit" value="Register" />
</form>

<script>
$(function () {
    $('#btnRegister').click(function () {
        debugger
        var sForm = $('#myForm').serialize();

        $.ajax({
            type: 'POST',
            url: 'https://localhost:44358/api/Account/Register',
            contentType: "application/json",
            dataType: "json",
            data: sForm,
            success: function () {
                alert('Success');
            },
            error: function (xhr, status, error) {

            }
        })
    })
})
</script>

In my Web API, I have this action method.

    // POST api/Account/Register
    [AllowAnonymous]
    [Route("Register")]
    public async Task<IHttpActionResult> Register(RegisterBindingModel model)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };

        IdentityResult result = await UserManager.CreateAsync(user, model.Password);

        if (!result.Succeeded)
        {
            return GetErrorResult(result);
        }

        return Ok();
    }

Using Postman, I have tested it and it works. I can insert into database but I hit the above error if I send it from html.

My RegisterBindingModel:

 public class RegisterBindingModel
{
    [Required]
    [Display(Name = "Email")]
    public string Email { get; set; }

    [Required]
    [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
    [DataType(DataType.Password)]
    [Display(Name = "Password")]
    public string Password { get; set; }

    [DataType(DataType.Password)]
    [Display(Name = "Confirm password")]
    [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
    public string ConfirmPassword { get; set; }
}

Added another normal controller in the same project to test. It passes the ModelState but hang at the line in bold.

[HttpPost]
    public ActionResult Register(RegisterBindingModel registerBindingModel)
    {
        if (!ModelState.IsValid)
        {
            return View();
        }
        using (var client = new HttpClient())
        {

            **HttpResponseMessage responsePost = GlobalVariables.WebApiClient.PostAsJsonAsync("Account/Register", registerBindingModel).Result;**
            if (responsePost.IsSuccessStatusCode)
            {
                // Get the URI of the created resource.
                Uri returnUrl = responsePost.Headers.Location;
                if (returnUrl != null)
                {
                    ViewBag.Message = "Added";
                }

            }
            else
            {
                ViewBag.Message = "Internal server Error: " + responsePost.ReasonPhrase;

            }
        }
        return View();
    }

GlobaVariable:

public class GlobalVariables
{
    public static HttpClient WebApiClient = new HttpClient();

    static GlobalVariables()
    {
        WebApiClient.BaseAddress = new Uri("http://localhost:44358/api/");         
        WebApiClient.DefaultRequestHeaders.Clear();
        WebApiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
    }
}

Anyone can give some clue here?

2
  • 1
    Since you return an HTTP 405 if your ModelState is not valid, I would check that first. Did you trace your HTTP request? Commented Jan 23, 2020 at 9:17
  • I tried to create another mvc ui project with use test. ModelState is true. Commented Jan 23, 2020 at 9:29

2 Answers 2

1

This was happening because of the default routing convention was not being followed initially but after your corrected your base url, then the API started working. According to the specs:

In ASP.NET Web API, a controller is a class that handles HTTP requests. The public methods of the controller are called action methods or simply actions. When the Web API framework receives a request, it routes the request to an action.

To determine which action to invoke, the framework uses a routing table. The Visual Studio project template for Web API creates a default route:

routes.MapHttpRoute(
    name: "API Default",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

Hence when you need to call your API, your base url should have the /api to it.

Sign up to request clarification or add additional context in comments.

Comments

1

method not allowed is when you try and do a post, to a get etc.

add the tag [HttpPost] on your endpoint.

// POST api/Account/Register
[AllowAnonymous]
[HttpPost]
[Route("Register")]
public async Task<IHttpActionResult> Register(RegisterBindingModel model)
{
    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    var user = new ApplicationUser() { UserName = model.Email, Email = model.Email };

    IdentityResult result = await UserManager.CreateAsync(user, model.Password);

    if (!result.Succeeded)
    {
        return GetErrorResult(result);
    }

    return Ok();
}

3 Comments

I have just tried but it is not working running from both register.html and mvc, localhost:44358/Home/Register. Even if I didn't have [HttpPost], how come it works if I send the data from Postman using Post method?
After I changed the web api url to add https, it now return bad request
It works now after I moved the api to become "/api/Account/Register" which I also not sure why

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.