Raza Ali
Raza Ali

Reputation: 595

ASP.Net MVC 4 WebAPI POST returns 404

I've looked at the many similar issues posted but couldn't find a solution that worked for me. So the call to Get is working fine but call to POST returns 404. I created a simple WebAPI project (MVC 4).

public class CasesController : ApiController
{
    [Inject]
    public ICaseManager CaseManager { get; set; }

    // GET api/cases
    public IEnumerable<Case> Get()
    {
        return CaseManager.ListCases();
    }

    // POST api/cases
    [HttpPost]
    public void Post([FromBody]Case objCase)
    {

    }
}

So when I navigate to http://localhost:34645/api/cases I get the following:

[{"CaseID":1,"CaseCode":"one","CaseDescription":"case one"},{"CaseID":2,"CaseCode":"two","CaseDescription":"case two"}]

I created another project (ASP.Net) and have an html file within it with the following code:

<script src="Scripts/jquery-2.0.3.js"></script>
<script src="Scripts/jquery-2.0.3.intellisense.js"></script>

<script type="text/javascript">
    function postData() {
        $.post('http://localhost:34645/api/cases', { "CaseID": 3, "CaseCode": "three", "CaseDescription": "case three" }).done(function (data) { alert("Success " + data); }).fail(function (xhr, textStatus, errorThrown) { alert("Error " + xhr.status); });
    }
</script>

Every time I click the button that invokes postData, I get an alert "Error 404".

Here are my routes:

Global.asax:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);
}

WebAPIConfig.Register:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        //RA: to get JSON
        var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
        config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);

    }
}

RouteConfig:

 public class RouteConfig
 {
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Please advise.

Upvotes: 2

Views: 5281

Answers (5)

BornToCode
BornToCode

Reputation: 10213

You write that you post to $.post('http://localhost:34645/api/cases'...

Either you change the url to include the action method name explicitly, like: $.post('http://localhost:34645/api/cases/post'.. or you add in your config.Routes.MapHttpRoute a default action which will be used when none action specified in the url

 config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { action="Post", id = RouteParameter.Optional }
        );

OR you can change your route to

  config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",               
            ); 

(without {action} and then web api will reach the Post method when you use a post http verb (it knows to do it automatically, but if you set a default action it'll override it)

Upvotes: 0

ossentoo
ossentoo

Reputation: 2019

Be careful about the order of the WebApi registration line. I found when I specifically had the Global.asax.cs code in this order it worked:

        AreaRegistration.RegisterAllAreas();
        GlobalConfiguration.Configure(WebApiConfig.Register);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);

Otherwise, it failed with 404 error.

Upvotes: 5

Raza Ali
Raza Ali

Reputation: 595

After different attempts, this article helped me the most:

WebAPI and CORS enabled REST services

I also installed the Ninject WebApi DependencyResolver package through NuGet.

Upvotes: 0

Spock
Spock

Reputation: 6992

Try below. It works for me. I have removed some properties for brevity.

public class CasesController : ApiController {
    // GET api/cases
    public IEnumerable<Case> Get() {
        var caseManager = new CaseManager();
        return caseManager.ListCases();
    }

    // POST api/cases
    [HttpPost]
    public string Post([FromBody]Case objCase) {
        return objCase.CaseName;
    }
}

public interface ICaseManager     {
    IEnumerable<Case> ListCases();
}

public class CaseManager     {
    public IEnumerable<Case> ListCases()
    {
        return new List<Case>() { new Case() { CaseID = 1, CaseName = "one" } };
    }
}

public class Case     {
    public int CaseID { get; set; }
    public string CaseName { get; set; }
}

View

<script type="text/javascript">
    //function postData() {
    //    $.post('http://localhost:58820/api/cases', { "CaseID": 3, "CaseCode": "three", "CaseDescription": "case three" })
    //        .done(function (data) { alert("Success " + data); }).fail(function (xhr, textStatus, errorThrown)
    //        { alert("Error " + xhr.status); });
    //}
$(document).ready(function () {
    $('#save-source').click(function (e) {

        e.preventDefault();
        var source = {
            'ID': 0,
            'CaseID': 3,
            'CaseName': "three",
        };
        $.ajax({
            type: "POST",
            dataType: "json",
            url: "/api/cases",
            data: source,
            success: function (data) {
                alert(data);
            },
            error: function (error) {
                jsonValue = jQuery.parseJSON(error.responseText);                    
            }
        });
    });
});


</script>

 @using (Html.BeginForm(null, null, FormMethod.Post, new { id = "myForm"}))
    {
        <input type="submit" id="save-source" name="save-source" value="Add" />
    }

Upvotes: 0

anaximander
anaximander

Reputation: 7140

If these are two separate solutions, check they're both running - it's possible that they're trying to share a server instance, so the WebAPI you're trying to hit isn't running when the other app is. If they're projects within the same solution, check that they're both set to run on startup, or again, the WebAPI won't be running when the ASP.NET project tries to access it.

Upvotes: 0

Related Questions