Run AngularUI and Asp.net WebApi on different ports - c#

I have 2 seperate project in different ports, one is asp.net web api and another is angularjsUI, which consumes the webapi service. When i call webapi service from my angular project, the service is not hit.
If both service and angularUi are in same project then there is no issue , i am able to use the service.
Technology used:
Vs2015,
Angularjs1.6,
WebApi2
How to make communication between these two seperate projects in different ports successful.
Example :
Step 1: These files are in my angularUI project
LoginController.js
$scope.RegisterClick=function(myregister) {
var apiRoute = "http://localhost:51002/api/LoginApi";
var registerdata = LoginService.post(apiRoute, registeruserdetails);
}
LoginService.js
myqcapp.service("LoginService", function ($http) {
this.post = function (apiRoute, Model) {
var loginresult = $http({
method: "post",
url: apiRoute,
dataType: 'json',
headers: {
"Content-Type": "application/json; charset=utf-8"
},
data: Model
});
return loginresult;
}
});
Step 2: In my WebApi project
LoginApiController.cs
public class LoginApiController : ApiController
{
[ResponseType(typeof(Register))]
public IHttpActionResult Post(Register registercls)
{
if (ModelState.IsValid)
{
registerbs.Add(registercls);
return CreatedAtRoute("DefaultApi", new { id = registercls.Userid }, registercls);
}
else
{
return BadRequest(ModelState);
}
}
}
WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{Controller}/{id}",
defaults: new {
Controller="LoginApi",
id = RouteParameter.Optional
}
);
}

You need to enable cross site scripting on your Project/web app that serves the web API.
Your UI/API consumer is in separate project/port and if cross site scripting (CORS) is disabled the API server won't consider the request as " same origin request ".
You need to call EnableCors() inside the Register(HttpConfiguration conf) method of WebApiConfig class in App_Start folder. If WebApiConfig is not present by default then you may have to add it.
Next you need to decorate your controller with [EnableCors] annotation, say my web page is at localhost:8080, just decorate it as :
[EnableCors(origins: "http://localhost:8080", headers: "*", methods: "*")]
public class LoginApiController : ApiController
{
.....
}
you could also allow any site to access your API by using * wildcard
[EnableCors(origins: "*", headers: "*", methods: "*")]
you need to learn more about CORS. You also need to address the security aspect of CORS.

Related

WebAPI 2 custom routing

I have added the custome routing to a WebAPI ASP.NET application, using framework 4.7.1, by adding the attribute on top of the method:
public class ShapeFileAnalysisController : ApiController
{
[HttpGet]
[Route("GetDataValues")]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public HttpResponseMessage GetDataValues()
{
string result = Models.ShapeFileReader.GetAdmin2();
HttpResponseMessage response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(result, Encoding.UTF8, "application/json");
return response;
}
}
but when I add [Route("...")} attribute the full URL changes from mysite.com/api/ShapeFileAnalysis to mysite.com/GetDataValues
the webapiconfig.cs is:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
What I should do to have still mysite.com/api/ShapeFileAnalysis/GetDataValues ?
Attribute routing uses the route template placed in the attribute.
Your route has only GetDataValues so that will become the full route path.
mysite.com/GetDataValues
If you place the desired route path
//GET api/ShapeFileAnalysis/GetDataValues
[HttpGet]
[Route("api/ShapeFileAnalysis/GetDataValues")]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public HttpResponseMessage GetDataValues() {
//...
}
Then you will get the desired path
mysite.com/api/ShapeFileAnalysis/GetDataValues
You can set a common prefix for an entire controller by using the [RoutePrefix] attribute
[RoutePrefix( "api/ShapeFileAnalysis" )]
public class ShapeFileAnalysisController : ApiController {
//GET api/ShapeFileAnalysis/GetDataValues
[HttpGet]
[Route("GetDataValues")]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public HttpResponseMessage GetDataValues() {
//...omitted for brevity
}
}
Reference Attribute Routing in ASP.NET Web API 2
It's posible that you are mixing two ways to implement a WebApi in Net framework as is mention on the Microsoft Documentation - https://learn.microsoft.com/en-us/aspnet/web-api/overview/web-api-routing-and-actions/routing-and-action-selection.
In the first one (the one that you are follow) the routing matching is throught the parameter of the verbs (GET, POST, PUT, DELETE), this means that when you do a Get you distinguish between method using the parameter's name (examples are aviable in Microsoft's Documentation mentioned before).
In the second one you can Add a Route and controller route on the top to tell the compiler in which route it should to expose the method.
I didn't have the time to test in VS my suggestion but I believe that you need to add one more attribute - RoutePrefixAttribute.
Your code should be be following:
[RoutePrefix( "api/ShapeFileAnalysis" )] // new line of code!
public class ShapeFileAnalysisController : ApiController
{
[HttpGet]
[Route("GetDataValues")]
[EnableCors(origins: "*", headers: "*", methods: "*")]
public HttpResponseMessage GetDataValues()
{
}
}
For this situation "mysite.com/api/ShapeFileAnalysis/GetDataValues"
If all requests will be in this template. You don't have to use Custom Route.
The other answer is the solution of the problem, but I want to offer a different alternative. Change default route and remove all route attributes.
Route Template add action tag.
Example:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Referance: Routing in ASP.NET Web API

C# Web API 405 Error on GET

I'm brand new to restful APIs after a decade on desktop development. I'm a little confused as to why I am getting a 405 attempting a GET for a controller.
My controller:
public class ApplicantsController : ApiController
{
/// <summary>
/// Gets the details of the applicant and their application
/// </summary>
/// <param name="applicantID">The ID of the applicant to get the most recent application and details for</param>
/// <returns></returns>
public HttpResponseMessage Get(int applicantID)
{
try
{
using (DbQuery query = new DbQuery("SELECT * FROM Applicants AS A WHERE A.ID = #ApplicantID",
new DbParam("#ApplicantID", applicantID)))
{
using (DataTable data = query.ExecuteDataTable())
{
if (data.Rows.Count > 0)
{
Applicant applicant = new Applicant(data.Rows[0]);
return new HttpResponseMessage()
{
Content = new StringContent(applicant.ToJson(), Encoding.UTF8, "text/html")
};
}
}
}
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
catch (Exception ex)
{
Methods.ProcessException(ex);
return new HttpResponseMessage(HttpStatusCode.InternalServerError);
}
}
public HttpResponseMessage Post(Applicant applicant)
{
if (applicant.Save())
{
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, applicant);
string uri = Url.Link("DefaultApi", new { id = applicant.ID });
response.Headers.Location = new Uri(uri);
return response;
}
return Request.CreateResponse(HttpStatusCode.InternalServerError, "Error saving applicant");
}
}
}
I have the same default routing in my WebApiConfig and confirmed that the way my controller is written it matches a standard Web API 2 controller with read, write, update methods. I've tried using DefaultAction, I've tried decorating methods with [HttpGet] and [AcceptVerbs]. Whenever I try to access the Get through either a browser myself or through ajax, I get a 405 (method not allowed).
Ajax test:
$("#TestGetApplicantButton").click(function (e) {
e.preventDefault();
alert("Getting Applicant...");
$.ajax({
type: "GET",
url: "/api/Applicants/108",
contentType: "application/json; charset-utf-8",
dataType: "json",
success: function (data) {
$("#ResponseDiv").html(JSON.stringify(data));
},
failure: function (errMsg) {
alert(errMsg);
}
});
});
Ajax works perfectly for all of the other controllers, showing the data returned (example: and it even calls the Post method on this controller just fine. Yet I can't get my Get to work. I don't see where I could be going wrong.
My routing:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
}
I've googled and checked here, but everyone seems to only have issues with POST, PUT, or DELETE, so I haven't found an answer for this. I've also tried removing the POST method in the controller - that gets me a 404 instead (not from my 404, I confirmed the code doesn't execute), which suggests for some reason the routing can't find my get method at all.
You need to add a default value to your applicantID parameter, since your route has the first parameter marked as RouteParameter.Optional.
public HttpResponseMessage Get(int applicantID = 0)
This will ensure that your Get method signature matches your "DefaultApi" route.

Issue in angularjs2 with restful web API

I am doing AngularJS2 with Restful web API , and getting some console errors while calling HTTP post. Errors are listed below,
Hope you help
Controller code snippet
namespace SoomWebApi.Controllers
{
[EnableCors(origins: "http://localhost:64336", headers: "*", methods: "*")]
public class UserController : ApiController
{
public HttpResponseMessage UserLogin([FromBody] LoginRequestData objValidate)
{
UserModelManager _UserModelManagerr = new Models.UserModelManager();
return Request.CreateResponse(HttpStatusCode.OK, _UserModelManagerr.Login(objValidate), GetJSONFormatter());
}
}
}
Webapiconfig code snippet
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
It look like a CORS problem .. try to put in your Startup.cs file in WebAPI something like:
using Microsoft.Owin;
using Owin;
public void Configuration(IAppBuilder app)
{
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
ConfigureAuth(app);
}
If you want to limit to some specific host ..try something like:
var corspolicy = new corspolicy
{
allowanymethod = true,
allowanyheader = true,
supportscredentials = true,
origins = { "http://www.example.com", "http://localhost:38091", "http://localhost:39372" }
};
app.usecors(new corsoptions
{
policyprovider = new corspolicyprovider
{
policyresolver = context => task.fromresult(corspolicy)
}
});
Your server should support CORS to allow access from different domains. Update your server configuration to allow only predefined set of domains to allow access.
Access-Control-Allow-Origin: "domains"
If you have this problem on debug only and do not plan use CORS after deploy - mostly local web server starts your Angular application on localhost:some-port and server deployed on localhost also - use IE for debugging - it works good even when your angular middleware and backend works on different ports.
If the code in production will be on the same domain as REST API, you can install chrome extension to avoid CORS error:
Chrome CORS extension

.NET Web api 2 stops working after sometime in IIS

I have two web API project DLLs in one solution.
Structure of my Project Solution:
In my solution, the projects are located as follows:
1) Base Solution
2) Base Web API
3) Module Web API
Hence, my solution is something like a BASE solution which contains many MODULES. Each Modules can contain its own Web APIs. Also, my Base Solution contains its own Web API
This is our structure.
My Problem:
It is working fine in my local run solution. When I host it to the IIS, it is working for few hours and then it stops working by throwing the error message "Error 404 found". When I try to access through URL directly which is something like "http://127.0.0.1:51/Products/Get", not working.
Visual Studio version:
Visual Studio Professional - 2015
IIS Version:
IIS - 7.5.7600
My approach:
I have a simple project which simulates this scenario. It has the same problem with my original project.
Web API For Base Module:
WepApiConfig under App_Start:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Base API Controller:
public class ValuesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
}
WebApiConfig.cs For Module Web API:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
//config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultModuleApi",
routeTemplate: "api/module/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Module API Controller:
public class ModulesController : ApiController
{
// GET api/values
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/values/5
public string Get(int id)
{
return "value";
}
}
NOTE from the above code:
The difference between the two APIConfig files is :
For Module Code:
routeTemplate: "api/module/{controller}/{action}/{id}"
For Base Code:
routeTemplate: "api/{controller}/{action}/{id}"
Global.asax:
namespace BaseSln
{
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
//GlobalConfiguration.Configure(WebApiConfig.Register);
var typesWithMyAttribute =
from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetLoadableTypes().Where(t1 => t1.Name == "WebApiConfig"
&& t1.GetMethod("Register") != null
&& t1.GetMethod("Register").IsStatic)
select new { Type = t, MethodInfo = t.GetMethod("Register") };
//register all the Routes
foreach (var type in typesWithMyAttribute)
{
var mi = type.MethodInfo;
Action<HttpConfiguration> action = null;
try
{
action = Delegate.CreateDelegate(typeof(Action<HttpConfiguration>), mi) as Action<HttpConfiguration>;
}
catch
{
//ignore the errors for now... should be handled somewhere else or logged.
}
if (action != null) GlobalConfiguration.Configure(action);
}
}
}
}
What I tried with the above project:
After hosting in IIS, I tried to access the path which is something like this:
For Base API:
http://localhost:51600/api/Values/Get
Returns:
value1
value2
For Module API
http://localhost:51600/api/Modules/Get
Returns:
value1
value2
My problem:
After sometime, when I try to access the same link, I am unable to get that. It says
status 404. Not Found
I have been working on this issue for 3 days, and I couldn't resolve the problem.
I have searched many articles in stackoverflow, but no luck.
Kindly help me to get rid off from this.
Thanks.
Can you check the GlobalConfiguration.Configuration.Routes in the Base Solution if you have all the routes for both the Base Web API and the Module Web API?

EnableCors failing in WebApi 5.2.3 for specific apicontrollers

So I followed the following tutorials:
enable-cors-in-webapi-2
ASPNET-WebAPI-Enable-Cors
enabling-cross-origin-requests-in-web-api
Each of them described a way to EnableCors for a controller, or you can add by global.
I followed the steps outlined in all 3 of them where in my App_Start/WebApiConfig.cs file I entered the following:
public static void Register(HttpConfiguration config)
{
config.EnableCors();
config.Routes.MapHttpRoute(
name: "Default",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { controller = "", action = "Get" }
);
}
And in my controller I added in:
[EnableCors(origins: "http://localhost:50247", headers: "*", methods: "*")]
public class TestController : ApiController
{ ... }
But when I went to run the program it gave me the following error:
XMLHttpRequest cannot load http://localhost:49705/api/Test/GetTestData. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:50247' is therefore not allowed access.
But when I make the following addition to the App_Start/WebApiConfig.cs to make EnableCors throughout the entire app:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
var cors = new EnableCorsAttribute(
origins: "*",
headers: "*",
methods: "*");
config.EnableCors(cors);
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
It worked. But if makes my decorated EnableCors attribute on my api controllers useless.
When I removed the [EnableCors] attribute from my apicontroller:
public class TestController : ApiController
{ ... }
It worked, because of what I did globally. Is there a reason for why this happened? Did a bug occur when upgrading from webapi 5.2.2 to 5.2.3?
The project is new using asp.net webapi start up templates in visual studio 2013.

Categories