Steve
Steve

Reputation: 4453

Web API Post error - HTTP Error 405.0 - Method Not Allowed

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?

Upvotes: 0

Views: 2727

Answers (2)

Rahul Sharma
Rahul Sharma

Reputation: 8302

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.

Upvotes: 1

davethecoder
davethecoder

Reputation: 3932

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();
}

Upvotes: 1

Related Questions