same method, Different output.The requested resource does not support http method 'GET' - asp.net-web-api2

My route is correctly configured, and my methods have the decorated tag.
Method "GetMessage" work fine but "DeleteAllLoc" return "The requested resource does not support http method 'GET'.".
They are the same...What is problem?
[RoutePrefix("api/Loc")]
public class LocController : ApiController
{
[Route("DeleteAllLoc")]
public string DeleteAllLoc()
{
return "OK";
}
[Route("GetMessage")]
public string GetMessage()
{
return "Hello";
}
}

Decorate your DeleteAllLoc method with the [HttpGet] attribute to specify that it's a GET request - I think it's inferring it as a DELETE because of the method name.

Related

ASP.Net Core required parameter binding fails to fail using FromBody

I'm developing an Asp.Net Core API.
My controller declaration
[ApiController]
public class BarController : Controller
{
...
}
My endpoint looks like this
[HttpPost, Route("bars")]
public async Task<ActionResult> DoAsync(
[FromBody] UpdateBars command)
{
// Do something with the command
return Ok(result);
}
The command looks like this
public class UpdateBars
{
[Required]
public IEnumerable<string> Ids { get; set; }
// ... more properties
}
Compatibility level is set to 2.1
public IServiceProvider ConfigureSharedServices(IServiceCollection services)
{
// ...
services.AddMvc()
.AddControllersAsServices()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
// ...
}
Old question: I'd expect this to return a 400 bad request with a missing Ids parameter, but it fails to return the binding error.
What am I doing wrong?
Updated question: I'd expect this to return a 400 bad request with a missing or empty Ids parameter. The response is as expected if the parameter is missing (null), but returns 200 ok if it is an empty collection.
Is it possible to change something so that I get a bad request when the parameter is present but empty?
You probably didn't put a [ApiController] attribute on your controller.
By default the validation is not 'automatic'.
If you don't want to put that attribute on your controller, you will have to validate the model yourself, in following way:
[HttpPost, Route("bars")]
public async Task<ActionResult> DoAsync(
[FromBody] UpdateBars command)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
// Do something with the command
return Ok(result);
}
You have more controll in that way, but if you just need to return a BadRequest with the model state, it will happen automatically if you put the [ApiController] on the controller.
Also in that case it will mark all action parameters as [FromBody], so putting that attribute on params is not needed
You should add the [ApiController] attribute. In that case, an automatic HTTP 400 response containing error details is returned when model state is invalid. For more information, see Automatic HTTP 400 responses. Automatic HTTP 400 responses.

How to retrieve current application root URL in .net core within a static method?

I am currently using the Request.Scheme and Request.Host to composite Uri object to get AbsoluteUri for my .net core MVC application.
Uri location = new Uri($"{Request.Scheme}://{Request.Host}");
string applicationRootURL = location.AbsoluteUri;
But this only works in a non-static method.
As I need to re-use this method in another controller, I am thinking to make this action method static. If I do that, the compiler will complaint about the Request.Scheme and Request.Host.
I am wondering what's other options I have to achieve this?
Thank you.
UPDATE:
This is what I have for ControllerA with ActionMethodA
public class ControllerA
{
public bool ActionMethodA()
{
Uri location = new Uri($"{Request.Scheme}://{Request.Host}");
string applicationRootURL = location.AbsoluteUri;
return false;
}
}
And in another ControllerB, I want to ActionMethodB to invoke ActionMethodA from ControllerA:
public class ControllerB
{
public void ActionMethodB()
{
var result = ActionMethodA();
}
}
Is creating an Extension Method to the ControllerA is the most proper way to handle this kind of scenario?
Thank you.
You can also define an extension method directly for the HttpRequest class and use the BuildAbsolute method of the UriHelper class to build the uri.
public static class HttpRequestExtensions
{
public static string GetURI(this HttpRequest request)
{
return UriHelper.BuildAbsolute(request.Scheme, request.Host);
}
}
And use it:
public IActionResult ContollerMethod()
{
var uri = Request.GetURI();
// your code
}
You can write an extension method to a controller or HttpContext object. In the following example I have added an extension method to the controller.
public static class ControllerExtensions
{
public static string GetURI(this Controller controller)
{
Uri location = new Uri($"{ controller.Request.Scheme}://{controller.Request.Host}");
string applicationRootURL = location.AbsoluteUri;
return applicationRootURL;
}
}
Once the extension method is written you can call it in the following manner.
public IActionResult Index()
{
var url = this.GetURI();
return View();
}
Make sure to import namespace of an extension method in your calling code

Spring & Reslet : is it possible to map a URL path component to a method argument?

I'm new to Restlet, but I've followed the tutorial on Restlet's own website and got a basic application up and running. What I'm doing right now is that I'm setting up a basic ServerResource and expose a #Get method.
What I'd like is to be able to invoke /user/{userId} and get the user representation back. Is it possible, somehow, to hand over the mapping of {userId} to Restlet, which in turn would invoke getUser(String userId) in my ServerResource?
Such feature (binding path variables into annotated method parameters) isn't natively supported in the framework. Such mapping in the annotated method signatures is only supported with input representation.
To get the path variables of a request, you can get them from the request object (method getAttribute), as described below:
public class UserServerResource extends ServerResource {
#Get
public User getUser() {
String userId = getAttribute("userId");
User user = (...)
(...)
return user;
}
}
If you want to share this path variable across several methods, you can define it as a instance variable (notice that a new instance of the server resource is created for each request unlike to Spring REST where each controller is a singleton and such variable must be defined in method signatures). We can leverage the method doInit of the server resource, as described below:
public class UserServerResource extends ServerResource {
private String userId;
private User user;
#Override
protected void doInit() throws ResourceException {
super.doInit();
userId = getAttribute("userId");
// for example
user = loadUser(userId);
// throws a status 404 if user can't be found
setExisting(user != null);
}
#Get
public User getUser() {
return user;
}
#Put
public User saveUser(User user) {
saveUser(user);
return user;
}
#Delete
public void deleteUser() {
deleteUser(user);
}
}
If you really want to use a mapping from request elements (like path variables, ...) to method parameters, you should use JAXRS. Restlet provides a support of this specification. Implementing a similar server resource as above but with JAXRS is described below:
#Path("/users/{userId}")
public class UserResource {
#GET
#Produces("text/xml")
public String getUser(#PathParam("userId") String userId) {
(...)
}
}
For more details, you can have a look at the corresponding documentation: http://restlet.com/technical-resources/restlet-framework/guide/2.2/extensions/jaxrs.
Hop it helps,
Thierry

Get the route value from url in webapi attribute routing

I have a webAPI controller which is like
Public class TestController:APIController
{
[Route(“Api/Test/{testId}/SubTest”)]
Public void Post(int subTestid)
{
}
}
Our requirement is to get the value of testId from the url inside the post method.
Could anyone suggest the best way to achieve this.
Looking at this link: http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2
The string "customers/{customerId}/orders" is the URI template for the
route. Web API tries to match the request URI to the template. In this
example, "customers" and "orders" are literal segments, and
"{customerId}" is a variable parameter.
public class OrdersController : ApiController
{
[Route("customers/{customerId}/orders")]
[HttpGet]
public IEnumerable<Order> FindOrdersByCustomer(int customerId) { ... }
}
It seems that you need to change subTestid to testId so it will be a match.

Default parameter value in MVC 4 Web API

I am curious why the ApiController handles default parameter values on actions differently than a 'regular' Controller.
This code works just fine, request to /Test means page gets value 1
public class TestController : Controller
{
public ActionResult Index(int page = 1)
{
return View(page);
}
}
This code doesn't work when a request is made to /api/Values. It fails with:
"The parameters dictionary contains a null entry for parameter 'page' of non-nullable type 'System.Int32' for method 'System.Collections.Generic.IEnumerable`1[System.String] Get(Int32)' in 'MvcApplication1.Controllers.Controllers.ValuesController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter."
public class ValuesController : ApiController
{
public IEnumerable<string> Get(int page = 1)
{
return new string[] { page.ToString() };
}
}
Any hints on why this is?
Try adding the [FromUri] or [FromForm] parameter attribute.
public class ValuesController : ApiController
{
public IEnumerable<string> Get([FromUri]int page = 1)
{
return new string[] { page.ToString() };
}
}
Mike Stall has two good posts about parameter binding in Webapi which does not work as it does in ASP MVC. The big problem to get used to is that you can only read the request body once in your pipeline. So if you need to read more than 1 complex object as a parameter, you probably need to resort to ModelBinding by parameter. I had a problem similar to yours when I was reading the content body earlier in the pipeline for logging purposes and did not realize about the read once restriction above and had to solve with my own custom model binder.
Explains model binding at http://blogs.msdn.com/b/jmstall/archive/2012/04/16/how-webapi-does-parameter-binding.aspx and then suggests a way to make WebAPI model binding more like ASP MVC http://blogs.msdn.com/b/jmstall/archive/2012/04/18/mvc-style-parameter-binding-for-webapi.aspx
Try defining as Nullable<T>:
public class ValuesController : ApiController
{
public IEnumerable<string> Get(int? page = 1)
{
return new string[] { page.ToString() };
}
}