Route Not Finding With WebAPI in MVC4 - asp.net-web-api

In my WebApiConfig.cs file I have the following route defined: (it's the only route defined here)
config.Routes.MapHttpRoute(
name: "DefaultApi2",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new {id = RouteParameter.Optional}
);
The POST I'm making is to:
http://localhost:17138/api/Account/Login
My controller is this:
namespace WebAPI.Api
{
public class AccountController : ApiController
{
[HttpPost]
public HttpResponseMessage Login(string username,string password)
{...
The error I'm getting is:
{"Message":"NoHTTPresourcewasfoundthatmatchestherequestURI'http://localhost:17138/api/Account/Login'.","MessageDetail":"Noactionwasfoundonthecontroller'Account'thatmatchestherequest."}
and from Phil's program it looks like the route should work. Any thoughts?

I changed my parameters for my Login method to
public HttpResponseMessage Login(FormDataCollection formDataCollection)
and it worked. It seems I'm missing something about how POST parameters are handled because in the formDataCollection, both username and password are there. I'm not sure what that is not the same as
public HttpResponseMessage Login(string username,string password)

Related

how to set up url routing with sub-paths

i am new to webapi and MVC in general. If I wanted to group my service URLs like this
/api/account/create
/api/account/login
/api/account/resetpass
Am I able to put all 3 method calls in the same controller file and somehow map a particular request to the right method?
Create a Controller named Account and Create 3 [GET, POST, PUT, DELETE] method and name them create , login ,resetpass.
By Default, this is the routing for MVC / API(Id can be optional)
route Template: "api/{controller}/{id}",
Example :
public class AccountController : ApiController
{
[HttpPost]
public string Create()
{
// CODE
}
[HttpPost] // or [HttpGet]
public string Login ()
{
// CODE
}
[HttpPost]
public string Resetpass()
{
// CODE
}
}
if you had trouble calling them, try to give them a specific route :
[HttpGet("GetSubject/{subject}")]
public int GetSubjectId(String subject)
{
//CODE
}
Please if you get any error or misunderstanding, don't hesitate to post a comment

WebApi with string parameter

My webapi method couldn't accept string parameter.
In post method in webapi controller , i could get only an optional string parameter, but when i test my method without parameter it get following error:
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.String Get(Int32)' .
[HttpPost]
public IHttpActionResult List(string munZone="")
{
}
in route config:
routes.MapRoute(
name: "DefaultApi3",
url: "api/{controller}/{action}"
);
routes.MapRoute(
name: "DefaultApi2",
url: "api/{controller}/{action}/{id}",
defaults: new { id = UrlParameter.Optional }
);
I need to send nullable string parameter instead of int id parameter
I found it,if i send param as object of class, this problem will resolve.
public class T{
public string munZone
}
[HttpPost]
public IHttpActionResult List(T t)
{
}

WebApi HTTPPOST Endpoint not being hit

I have the following simple HTTPPOST endpoint;
[AllowAnonymous]
[HttpPost]
[Route("forgotPassword")]
public IHttpActionResult ForgotPassword(string userName, string callbackUrl)
Where the controller is decorated as follows;
[Authorize]
[RoutePrefix("api/accounts")]
public class AccountsController : ApiController
Now when i try to test this endpoint in postman, using the following url;
http://localhost:11217/api/accounts/forgotPassword
with the strings in the body of the message
I get the following return.
{ "Message": "No HTTP resource was found that matches the request
URI 'http://localhost:11217/api/accounts/forgotPassword'.",
"MessageDetail": "No action was found on the controller 'Accounts'
that matches the request." }
Now I would rather not have to create a model for the two strings (if possible). Also if I try to put the params in the query string I get a potantially dangerous request response
http://localhost:11217/api/accounts/forgotPassword/test&callbackUrl=local
Can anyone help please?
If you want to send mulitple parameters when doing a post request you should create a DTO that contains the parameters as
public class forgetPasswordDTO
{
public string userName { get; set; }
public string callbackUrl { get; set; }
}
Then add the DTO as a method parameter with the [FromBody]
[AllowAnonymous]
[HttpPost]
[Route("forgotPassword")]
public IHttpActionResult ForgotPassword([FromBody] forgetPasswordDTO data)
And in you client, create the object as
var data = {
'userName': user,
'callbackUrl': url
};
And add it to the body of the request.
Here's a nice article about this topic

Multiple Get methods in ASP.Net Web API

Hi I've 2 different get methods with the below signature and my routing is as follows:
[ActionName("Data")]
public Dictionary<int, string> GetData(int ID)
{
}
[ActionName("Name")]
public Dictionary<int, string> GetName(int ID)
{
}
var route = routes.MapRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
But api/{controller}/Data/9 and api/{controller}/Name/10 are both calling the first method GetData.
Can someone please guide me to fix this.
You will have to decorate your controllerclass with the [RoutePrefix("api/ControllerName")] as well as do the following:
[Route("Data")]
public Dictionary<int, string> GetData(int ID)
{
}
[Route("Name")]
public Dictionary<int, string> GetName(int ID)
{
}
var route = routes.MapRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
You can get a little more fancy with the Route attribute.
[Route("Name/{ThisIsMyIdVariableName}"), HttpGet]
public HttpResponseMessage GetName(int ThisIsMyIdVariableName) { /*code here*/ }
Now you can keep the idea of a pretty url without having to use routes.MapRoute and can call the url like domain.com/Name/19. You can use multiple variable names wrapped with {} in the route and keep your urls pretty and restful when passing multiple variables.
This approach is also very useful if you have the need to version your api controller.
I know this should be a comment instead of an answer, but I don't have the required reputation to comment yet, and I'd like to help. Are both of the above methods returning data based on their id (PK) value? The reason both methods are calling the first method in your Web API server is because they're both appending the same URL extension to the server. A quick and easy way to differentiate these methods could be to change one of the 2 to accept a string that you could then convert back to an int. For instance:
//api/Customer/5
public Dictionary<int, string> GetData(int ID)
{
}
//api/Customer?CustID={custID]
public Dictionary<int, string> GetName(string custID)
{
//convert string to int and continue code
}
This might not be best practice, but this is what I've done in the past when needing to differentiate between GET/POST methods in my web api server. For deserializing, you could use a class like JsonConvert if you're using Json, etc. Then your calls to your controller will add the appropriate URL extensions as defined in the comments I left above the methods. Let me know if you'd like additional explanation.

Attribute Routing in WEB API overwrite route in Controller

I'm trying to add attribute routing to a ApiController like so:
public class PhoneNumbersController : ApiController
{
// GET BY ID
public PhoneNumber GetById(int id)
{
return PhoneNumbersSelect(id)[0];
}
// GET BY ID TypeOFPhoneNumbers/Id
[Route("api/typeOfPhoneNumbers/{id}")]
public TypeOfPhoneNumber GetTypeOfPhoneNumberById(int id)
{
return TypeOfPhoneNumbersSelect(id)[0];
}
}
My config looks like this:
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
I'm getting a 500 Error when trying to call api/phoneNumbers/1. If I comment out the GetTypeOfPhoneNumbersId() function the default controller GetById() works fine. What am I doing wrong? Am I not allowed to declare a unique route in the ApiController because of the way the config is set up?
Also, as I just found out, calling the api/typeOfPhoneNumbers/1 returns a 404 error, so that routing doesn't work at all.
Thanks for any help!
I believe you miss the controller name (phoneNumbers) in your route, this is a working code (I've tested it)
public class PhoneNumbersController : ApiController
{
// GET BY ID
[HttpGet]
public PhoneNumber GetById(int id)
{
return PhoneNumbersSelect(id)[0];
}
// GET BY ID TypeOFPhoneNumbers/Id
[HttpGet]
[Route("api/phoneNumbers/typeOfPhoneNumbers/{id:int}")]
public TypeOfPhoneNumber GetTypeOfPhoneNumberById(int id)
{
return TypeOfPhoneNumbersSelect(id)[0];
}
}
Could you try to access TypeOFPhoneNumbers's resource like that : ~api/typeOfPhoneNumbers?id=1

Resources