Multiple HttpPost action with the same parameter in Web API Controller - c#

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

Related

Angular 2/4 - Call PUT Method in a Asp Net WebApi gives Bad Request (400)

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

ASP.Net WebAPI 2 404 Error - Insights Say Different

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

web api routing with action and id

I am new in using web api and I am trying to call a specific method in my controller.
I have
global.asax
protected void Application_Start()
{
GlobalConfiguration.Configure(WebApiConfig.Register);
}
the WebApiConfig class with these routings
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new
{
id = RouteParameter.Optional
}
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new
{
action="DefaultAction",
id = RouteParameter.Optional
}
);
and my controller
[HttpGet]
public HttpResponseMessage GetPatSummary(string PatId)
{
PatientSummary Pat = new PatientSummary();
HttpResponseMessage Response = new HttpResponseMessage();
string yourJson = Pat.GetPatient(PatId);
Response = this.Request.CreateResponse(HttpStatusCode.OK, yourJson);
return Response;
}
[ActionName("DefaultAction")] //Map Action and you can name your method with any text
public IHttpActionResult GetPatient(int id)
{
Object Obj = new object();
if (Obj!=null)
{
return NotFound();
}
return Ok(Obj);
}
the URL I am using is
http://localhost/mdmwapi/api/MdmwPatientController/GetPatSummary/sgdgdgddhdhd1334254
but I get this error
A path segment cannot contain two consecutive parameters. They must be separated by a '/' or by a literal string.
I am getting nut :-)
Use attribute routing
[HttpGet]
[Route("api/MdmwPatientController/GetPatSummary/{PatId}")]
public HttpResponseMessage GetPatSummary(string PatId)
{
PatientSummary Pat = new PatientSummary();
HttpResponseMessage Response = new HttpResponseMessage();
string yourJson = Pat.GetPatient(PatId);
Response = this.Request.CreateResponse(HttpStatusCode.OK, yourJson);
return Response;
}
then you can request it using
http://localhost/api/MdmwPatientController/GetPatSummary/yourpatid
also you can map any url using attribute routing this way
the solution is a combination of a new route and a mistake in the URL
the new routes are now these ones
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute
(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new
{
id = RouteParameter.Optional
}
);
config.Routes.MapHttpRoute(
name: "ApiMethodCall",
routeTemplate: "api/{controller}/{action}/{PatId}",
defaults: new
{
controller= "MdmwPatient",
action= "GetPatSummary"
}
);
and the error in the URL was that although the controller class name is MdmwPatientController I have to omit the "controller" suffix when calling from the test client, so the correct url is
http://localhost/mdmwapi/api/MdmwPatient/GetPatSummary/sgdgdgddhdhd1334254

Multiple POST-request in web api

I need to use multiple POST-requests in web API but get an error: "Multiple actions were found that match the request..."
I have 2 POST-requests in my controller:
public void PostStart([FromBody]string value)
{
CookieHeaderValue cookie = Request.Headers.GetCookies("user").FirstOrDefault();
...
}
public void PostLogin([FromBody]string value)
{
CookieHeaderValue cookie = Request.Headers.GetCookies("user").FirstOrDefault();
...
}
My route file looks like this currently:
public static void Register(HttpConfiguration config)
{
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "apistart",
routeTemplate: "Home/api/values/start/{id}",
defaults: new { action = "PostStart", id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "apilogin",
routeTemplate: "Home/api/values/login/{id}",
defaults: new { action = "PostLogin", id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
If I remove on of the requests from the controller, everything works fine, so my routes seem valid, but when both of requests are present, router can't find the right one.
Any thoughts?
I've tried alredy to use another default route but it changes nothing:
routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
You can use [HttpPost] attribute to specify request method:
[HttpPost]
public void Start([FromBody]string value)
{
CookieHeaderValue cookie = Request.Headers.GetCookies("user").FirstOrDefault();
...
}
[HttpPost]
public void Login([FromBody]string value)
{
CookieHeaderValue cookie = Request.Headers.GetCookies("user").FirstOrDefault();
...
}
That will allows you to use as many post actions as you want with using default action-based route rule.
routes.MapHttpRoute(
name: "ActionApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
You should use RouteAttribute to make it work:
[Route("start")]
public void PostStart([FromBody]string value)
{
CookieHeaderValue cookie = Request.Headers.GetCookies("user").FirstOrDefault();
...
}
[Route("login")]
public void PostLogin([FromBody]string value)
{
CookieHeaderValue cookie = Request.Headers.GetCookies("user").FirstOrDefault();
...
}
WebApi doesn't take into consideration method name, only first word to resolve http method. Thats why you have error which says about "Multiple actions..." - there are two actions which can handle POST request.

MVC AngularJs Handling query string

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!

Categories

Resources