11
votes

So, I am stuck in a strange behavior, that is, I am able to send(or POST) data using Postman (plugin of chrome) or using RESTClient(extension of Firefox),

enter image description here

but not able to send it from my html file which lies outside the project. It shows following error when i open the html in chrome:

OPTIONS http://localhost:1176/api/user/ 405 (Method Not Allowed)
XMLHttpRequest cannot load http://localhost:1176/api/user/. Invalid HTTP status code 405 

I am not able to make out why is this happening. Following are the details, you might need to help me solve my error:

UserController.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using WebAPIv2.Models;

namespace WebAPIv2.Controllers
{
    public class UserController : ApiController
    {
        static IUserRepository userRepository = new UserRepository();

        [HttpGet]
        public List<TableUser> GetAllUsers()
        {
            return userRepository.GetAll();
        }

        [HttpGet]
        public HttpResponseMessage GetUser(int id)
        {
            TableUser user = userRepository.Get(id);
            if (user == null)
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "User Not found for the Given ID");
            }

            else
            {
                return Request.CreateResponse(HttpStatusCode.OK, user);
            }
        }

        [HttpPost]
        public HttpResponseMessage PostUser(TableUser user)
        {
            user = userRepository.Add(user);
            var response = Request.CreateResponse<TableUser>(HttpStatusCode.Created, user);
            string uri = Url.Link("DefaultApi", new { id = user.UserId });
            response.Headers.Location = new Uri(uri);
            return response;
        }

        [HttpPut]
        public HttpResponseMessage PutUser(int id, TableUser user)
        {
            user.UserId = id;
            if (!userRepository.Update(user))
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Unable to Update the User for the Given ID");
            }
            else
            {
                return Request.CreateResponse(HttpStatusCode.OK);
            }
        }

        [HttpDelete]
        public HttpResponseMessage DeleteProduct(int id)
        {
            userRepository.Remove(id);
            return new HttpResponseMessage(HttpStatusCode.NoContent);
        }
    }
}

User.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebAPIv2.Models
{
    public class User
    {
        public int UserId { get; set; }
        public string UserName { get; set; }
        public string Password { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Email { get; set; }
    }
}

IUserRepository.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WebAPIv2.Models
{
    interface IUserRepository
    {
        List<TableUser> GetAll();
        TableUser Get(int id);
        TableUser Add(TableUser user);
        void Remove(int id);
        bool Update(TableUser user);
    }
}

UserRepository.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace WebAPIv2.Models
{
    public class UserRepository : IUserRepository
    {
        MastarsFriendsMVCDatabaseEntities userEntities;

        public UserRepository()
        {
            userEntities = new MastarsFriendsMVCDatabaseEntities();
        }

        public List<TableUser> GetAll()
        {
            //throw new NotImplementedException();

            return userEntities.TableUsers.ToList();
        }

        public TableUser Get(int id)
        {
            //throw new NotImplementedException();

            var users = userEntities.TableUsers.Where(x => x.UserId == id);
            if (users.Count() > 0)
            {
                return users.Single();
            }
            else
            {
                return null;
            }
        }

        public TableUser Add(TableUser user)
        {
            //throw new NotImplementedException();

            if (user == null)
            {
                throw new ArgumentNullException("item");
            }
            userEntities.TableUsers.Add(user);
            userEntities.SaveChanges();
            return user;
        }

        public void Remove(int id)
        {
            //throw new NotImplementedException();

            TableUser user = Get(id);
            if (user != null)
            {
                userEntities.TableUsers.Remove(user);
                userEntities.SaveChanges();
            }
        }

        public bool Update(TableUser user)
        {
            //throw new NotImplementedException();

            if (user == null)
            {
                throw new ArgumentNullException("student");
            }

            TableUser userInDB = Get(user.UserId);

            if (userInDB == null)
            {
                return false;
            }

            userEntities.TableUsers.Remove(userInDB);
            userEntities.SaveChanges();

            userEntities.TableUsers.Add(user);
            userEntities.SaveChanges();

            return true;
        }
    }
}

WebApiConfig.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Web.Http;

namespace WebAPIv2
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();
            //config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

index.html:

<!DOCTYPE html>
<html>
    <head>
        <title>TODO supply a title</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">

        <!--<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>-->
        <script src="http://code.jquery.com/jquery-2.1.0.min.js"></script>
    </head>
    <body>
        <script>
            $(document).ready(function() {
//                jQuery.support.cors = true;
//                $.ajax({
//                    url: "http://localhost:1176/api/user/1",
//                    headers: {"Accept": "application/json"},
//                    type: "GET",
//                    success: function(data) {
//                        alert(JSON.stringify(data));
//                    },
//                    error: function() {
//                        alert("Error");
//                    }
//                });
//            });

                var user = {
                    UserName: "Disha",
                    Password: "disha123",
                    FirstName: "Disha",
                    LastName: "Vora",
                    Email: "[email protected]"
                };

                $.ajax({
                    url: 'http://localhost:1176/api/user/',
                    type: 'POST',
                    data: JSON.stringify(user),
                    crossDomain: true,
                    headers: {"Accept":"application/json" , "Content-Type":"application/json"},
                    success: function(data) {
                        alert('User added Successfully');
                    },
                    error: function() {
                        alert('User not Added');
                    }
                });
            });
        </script>
    </body>
</html>

Web.config:

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=301879
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <appSettings></appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5">
      <assemblies>
        <add assembly="System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      </assemblies>
    </compilation>
    <httpRuntime targetFramework="4.5" />
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <modules runAllManagedModulesForAllRequests="true">
      <remove name="WebDAVModule" />
    </modules>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Request-Headers:" value="*" />
        <add name="Access-Control-Request-Method:" value="*" />
        <add name="Access-Control-Allow-Methods" value="*" />
        <!--<add name="Allow" value="*"/>-->
      </customHeaders>
    </httpProtocol>
    <handlers>
      <remove name="WebDAV" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
    <directoryBrowse enabled="true" />
  </system.webServer>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>
  <connectionStrings>
    <add name="MastarsFriendsMVCDatabaseEntities" connectionString="metadata=res://*/Model.csdl|res://*/Model.ssdl|res://*/Model.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=WIN-WWU3DMLR6PX\PIXIELIT;initial catalog=MastarsFriendsMVCDatabase;persist security info=True;user id=sa;password=sa_12345;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />
  </connectionStrings>
</configuration>
4
@MilindAnantwar Sir, I am already applying the solution in my project. But, no success... :(Chintan Soni

4 Answers

25
votes

Ok. Solved the problem with the help of @martennis answer, but with a little correction.

Every things perfect, just to take care is, we need to enter following command in Package Manager Console:

Install-Package Microsoft.AspNet.WebApi.Cors –IncludePrerelease

Instead of the one shown in the link provided by, @martennis, and after that, my WebApiConfig.cs was updated as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;
using System.Web.Http.Cors;

namespace WebApiRESTfulwithJSON
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services
            var cors = new EnableCorsAttribute("*", "*", "*");
            config.EnableCors(cors);

            // Web API routes
            config.MapHttpAttributeRoutes();

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

Hence, solved the problem...!!!

Now, I will able to use my web services from anywhere, calling it from mobile applications, web applications or desktop applications.

For, how to create them from scratch, I wrote my first blog on this (...inspite of being android developer, never tried to write a blog for Android :-P Anyways...)

Link: http://programmingwithease.wordpress.com/2014/06/18/learning-asp-net-web-api-2-using-c/

17
votes

WebApi probably blocks the CORS request. To enable CORS on WebApi, use the Microsoft.AspNet.WebApi.Cors package. For further details, check http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api

0
votes

No need webconfig, all you need is to add:

  services.AddCors(o => o.AddPolicy("MyPolicy", builder =>
            {
                builder.AllowAnyOrigin()
                       .AllowAnyMethod()
                       .AllowAnyHeader();
            }));
-1
votes

Removing "using System.Web.MVC" from controller class solved this problem for me.