I am currently unable to access my api controller actions. I have an MVC app which calls the api through ajax calls in my javascript.
My API method is:
[HttpPost, Route("api/Communication/AddLink")]
public HttpResponseMessage AddLink([FromBody]int id)
{
//DO STUFF
return Request.CreateResponse(HttpStatusCode.OK, returnData);
}
my ajax call is:
$.ajax({
cache: false,
url: serviceEndpoint + 'api/Communication/AddLink',
type: 'POST',
data: { id: commid },
headers:{
Authorization: 'Bearer ' + token
},
success: function (data) {
console.log(data);
}
});
I retrieve my token as follows:
public async static Task<AuthenticationResult> GetTokenAsync(AuthenticationContext ctx, string resourceId)
{
ClientCredential credential = new ClientCredential(OfficeSettings.ClientId, OfficeSettings.ClientSecret);
var userObjectId = ClaimsPrincipal.Current.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
UserIdentifier ident = new UserIdentifier(userObjectId, UserIdentifierType.UniqueId);
var redirectUrl = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
try
{
AuthenticationResult result = await ctx.AcquireTokenSilentAsync(resourceId, credential, ident);
//var result = await ctx.AcquireTokenAsync(resourceId, credential);
LastAuthority = ctx.Authority;
return result;
}
catch (AdalException e)
{
logger.Error(e, "AcquireTokenSilentAsync: " + e.Message);
ctx.TokenCache.Clear();
return null;
}
catch (Exception ex)
{
throw ex;
}
}
and here is my routing from my WebApiConfig.cs:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApiWithAction",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
// DI Config
var container = new UnityContainer();
/// Register Types
container.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
}
This works in fiddler if i add the [AllowAnonymous] attribute to my API action but doesnt work inside the app however for obvious reasons this is not a solution.
When i attempt it through fiddler i get the error:
IDX10803: Unable to create to obtain configuration from: 'https://login.microsoftonline.com/.well-known/openid-configuration'
Any help with this would be greatly appreciated as i am out of ideas on this one. I am happy to provide further code and info if needed.
Thanks,
EDIT
A little additional info. My Api is set to start at localhost:44391 however when its loaded the url is https://localhost:44391/Error/GenericError. Does this possibly indicate something has gone wrong on start up? If so how do i debug this correctly?
Related
I have a Angular 4 app that need to call an WebApi created in visual Studio (asp.net).
The "get" method is Ok, I call and receive the expected response, but when I try to call the PUT or POST method, I always receives a BAD REQUEST (400) error.
My Angular Service:
public AvisoLido(aviso:Aviso) {
let headers:Headers = new Headers({'Content-Type': 'application/json'});
let options:RequestOptions = new RequestOptions({method:RequestMethod.Post, headers:headers})
let obj = JSON.stringify(aviso.IdAviso);
console.log(obj);
let url = "http://localhost:11730/api/Home/"
return this.http.post(
url,
obj,
options
)
.map((resposta:Response) => console.log(resposta.json()));
}
CONTROLLER CODE:
[EnableCors(origins: "http://localhost", headers: "*", methods: "*")]
public class HomeController : ApiController
{
[System.Web.Http.HttpGet]
public List<Aviso> GetAvisos(int idUsuario, string situacao)
{
AvisoBO bo = new AvisoBO();
return bo.ListAvisoPorUsuario(idUsuario);
}
[System.Web.Mvc.HttpPost]
public Aviso PostAviso([FromBody] Aviso obj)
{
return new Aviso();
}
}
WebApiConfig:
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new {action="*", id = RouteParameter.Optional }
);
config.EnableCors();
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
config.Formatters.Remove(config.Formatters.XmlFormatter);
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);//);
I've tried to change the Angular Service, passing content type "application/x-www-form-urlencoded" instead of Json format, and the controller method fires, but the parameter is always null in this case.
Anyone could help in this issue ?
Thanks a loT!
[System.Web.Mvc.HttpPost]
should be:
[System.Web.Http.HttpPost]
Mini generic example below
[System.Web.Http.HttpPost]
public MyReturnObject PostAndReturnSomething([FromBody]MyInputObject args)
{
return null;
}
I understand that this question has been asked several times already and I have looked at a lot of the questions, but none of the answers have worked for me thus far.
I am working with an ASP.Net WebAPI 2 Controller using .Net 4.5.2 and posting using Ajax.
I immediately get a 404 error, however looking at insights it shows that there are x amount of requests to that controller and that action\method but its returning a 404 immediately.
This is the the method, and would be grateful if anyone could help me.
[System.Web.Mvc.HttpPost()]
public int InsertRecord(Models.Person model)
{
if (ModelState.IsValid)
{
var person = new Person
{
FirstName = model.FirstName,
LastName = model.LastName,
DateOfBirth = Convert.ToDateTime(model.DateOfBirth)
};
_dbContext.People.Add(person);
_dbContext.SaveChanges();
var id = person.P_id;
return id;
}
else
{
throw new Exception("Invalid Data", null);
}
}
which is being called from my Ajax as follows;
$("#btnSave").click(function () {
$('#FirstName').valid();
$('#LastName').valid();
$('#DateOfBirth').valid();
if ($('#FirstName').valid() &&
$('#LastName').valid() &&
$('#DateOfBirth').valid()) {
//console.log("save clicked");
var jsonData = {
firstName: $('#FirstName').val(),
lastName: $('#LastName').val(),
dateofBirth: $('#DateOfBirth').val()
}
$.ajax(
{
type: "POST", //HTTP POST Method
url: "http://localhost:56658/AddPerson/InsertRecord", // Controller/View
data: jsonData,
success: function (response) {
if (response != null && response.success) {
alert(response.responseText);
} else {
// DoSomethingElse()
alert(response.responseText);
}
},
error: function (response) {
alert("error!"); //
console.log(response);
}
});
return false;
}
});
Edit
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 }
);
routes.MapRoute(
name: "AddPerson",
url: "{controller}/{action}",
defaults: new { controller = "AddPerson", action = "InsertRecord"}
);
}
}
Edit 2
This is the global asax file contents
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Edit 3
public static class WebApiConfig
{
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 }
);
}
}
As this is suppose to be a Wep API it should try to follow that design intent
Check for WebApiConfic where there is usually
public static class WebApiConfig {
public static void Register(HttpConfiguration config) {
// Attribute routing.
config.MapHttpAttributeRoutes();
// Convention-based routing.
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
Notice the api prefix of the default route. This configures how web API endpoints will be called. The api prefix is to avoid route conflicts with the normal MVC framework.
Url would end looking like api/AddPerson
next make sure controller is create properly and follows suggested design. Try to avoid adding too many responsibilities to the controller. Controllers are a UI concern and should be as lean as possible.
public interface IAddPersonCommand {
int? InsertRecord(Models.Person model model);
}
public class PersonController : ApiController {
private readonly IAddPersonCommand service;
public PersonController(IAddPersonCommand service) {
this.service = service;
}
[HttpPost]
public IHttpActionResult Post([FromBody]Models.Person model) {
if (ModelState.IsValid) {
var id = service.InsertRecord(model);
if(id !=null) {
return Ok(id);
}
}
//If we get this far bad request
return BadRequest();
}
}
I'm developing a web application using ASP.NET Web Api and angularJs.
I have a web api controller like this:
[ActionName("AddNewState")]
public object PostAddNewState(RegionInformation newStateParam)
{
RegionOperations regionOperation = new RegionOperations(newStateParam.StateName);
RegionInformation newStateInformation = regionOperation.NewStateInformation;
var text = new
{
newStateInformation
};
return JsonConvert.SerializeObject(text);
}
[ActionName("AddNewCity")]
public object PostAddNewCity(RegionInformation newCityParam)
{
var text = new
{
message="Hello"
};
return JsonConvert.SerializeObject(text);
}
and in client side I have these functions for sending POST request:
$scope.AddNewState = function () {
$http({
method: "POST",
url: "api/RegionManagement/AddNewState",
data: {
StateName: $scope.state
}
}).then(function (response) {
var obj = JSON.parse(response.data);
$scope.States.push({ text: obj.newStateInformation.StateName, value: obj.newStateInformation.ID });
});
};
$scope.AddNewCity = function () {
$http({
method: "POST",
url: "api/RegionManagement/AddNewCity",
data: {
ParentID: $scope.RegionInptes.ParentID,
CityName: $scope.city
}
}).then(function (response) {
var obj = JSON.parse(response.data);
alert(obj.message);
});
};
When I execute $scope.AddNewCity or $scope.AddNewState I face with 500 Internal Server Error.if I comment AddNewCity action in web api controller then I can execute $scope.AddNewState successfully.
I searched for using multiple HTTPPost in a web api controller and try this solution: Multiple HttpPost method in Web API controller, but nothing happened and I still have that error.
UPDATE
This is my config file:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ControllerOnly",
routeTemplate: "api/{controller}"
);
config.Routes.MapHttpRoute(
name: "ControllerandId",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ControllerAndAction",
routeTemplate: "api/{controller}/{action}"
);
}
The order in which you register your routes is important. register more specific routes first and the more general routes after.
public static void Register(HttpConfiguration config) {
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ControllerAndAction",
routeTemplate: "api/{controller}/{action}/{id}"
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "ControllerandId",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
You should also update the controller to be a little more specific as to what it can handle.
public class RegionManagementController : ApiController {
[HttpPost]
[ActionName("AddNewState")]
public object PostAddNewState(RegionInformation newStateParam) { ... }
[HttpPost]
[ActionName("AddNewCity")]
public object PostAddNewCity(RegionInformation newCityParam) { ... }
}
May be this is because of the number of parameters in the request url
[ActionName("AddNewState")]
public object PostAddNewState(RegionInformation newStateParam)
{
RegionOperations regionOperation = new RegionOperations(newStateParam.StateName);
RegionInformation newStateInformation = regionOperation.NewStateInformation;
var text = new
{
newStateInformation
};
return JsonConvert.SerializeObject(text);
}
[ActionName("AddNewCity")]
public object PostAddNewCity(RegionInformation newCityParam)
{
RegionOperations regionOperation = new RegionOperations(newCityParam.ParentID, newCityParam.CityName);
RegionInformation newStateInformation = regionOperation.NewStateInformation;
var text = new
{
newStateInformation
};
return JsonConvert.SerializeObject(text);
}
I have CourseAPi Controller that containing follwing method :
public IEnumerable<CoursesDTO> Get(int id)
{
var x = _uniManager.GetCourses(id);
return x;
}
i want to send id from URl to this method using Angualr js
the AngularJs controller :
app.controller('CRUD_OperController', function ($scope, $filter, CRUD_OperService, $location) {
GetAllRecords1();
function GetAllRecords1() {
var id = 12;
var promiseGetSingle = CRUD_OperService.get(id);
promiseGetSingle.then(function (pl)
{ $scope.Courses = pl.data },
function (errorPl) {
// $log.error('Some Error in Getting Records.', errorPl);
});
}
});
My angular service :
app.service('CRUD_OperService', function ($http) {
//Get All Student
this.getAllStudent = function () {
return $http.get("/api/CourseApi/" );
}
//Get Single Records
this.get = function (id) {
return $http.get("/api/CourseApi/" + id);
}
});
my webapi config
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi1",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.EnableSystemDiagnosticsTracing();
}
Update : it return me error
GET http://localhost:54070/api/CourseApi/12 404 (Not Found)
This is the format I have used for such a task:
this.$http({
method: 'GET',
url: 'api/courseapi/' + id
}).then(function (pl) {
$scope.Courses = pl.data
}, function (errorPl) {
$log.error('Some Error in Getting Records.', errorPl);
});
Is this what you are asking?
I can suggest two options:
The first one: configure routes in your angular controller using ng-route, inject $routeParams module and then retrieve the parameters using it. See this link and the Angular doc for more info.
The second option is to get url location and manipulate string in order to get the parameter:
var tokens = $location.absUrl().split("/");
var id = tokens[5]
I prefer the first option, it's "cleaner" than the second. Hope it can help you!
I have the trouble with AuthenticationConfiguration, when I put the AuthenticationConfiguration in the WebApiConfig my $http request stop to work. I get error Failed to load resource: the server responded with a status of 403 (HTTPS Required.).
Angular request
$http.get(defaultUrl + '/' + 'IsLoggedIn');
public class AuthenticationServiceController : ApiController
{
[System.Web.Http.HttpGet]
public HttpResponseMessage IsLoggedIn()
{
var loged = System.Web.HttpContext.Current.User.Identity.IsAuthenticated;
return Request.CreateResponse<bool>(System.Net.HttpStatusCode.OK, loged);
}
}
WebApiConfig.cs
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var authConfig = new AuthenticationConfiguration
{
InheritHostClientIdentity = true,
ClaimsAuthenticationManager = FederatedAuthentication.FederationConfiguration.IdentityConfiguration.ClaimsAuthenticationManager
};
// setup authentication against membership
authConfig.AddBasicAuthentication((userName, password) => Membership.ValidateUser(userName, password));
config.MessageHandlers.Add(new AuthenticationHandler(authConfig));
}