webapi error Multiple actions were found that match the request - c#

I have an accountcontroller that has 2 actions here are the declarations:
HttpResponseMessage PostAccount([FromBody] Account account)
public HttpResponseMessage PostLogin([FromBody]string email,[FromBody] string pass)
Running in fiddler, I am receiving the error Multiple actions were found that match the request. Im a little confused on whats going on. Should I make two controllers just for Login and Register? is that standard practice.

You can only have one parameter that comes from the body in Web API. If you want multiple things in the body, you should wrap them in a container class.
The error you're getting is happening because you have two actions that start with "Post". You can either create separate controllers, which makes sense if you're posting different types of entities. Or you can use action-based routing and create a route that looks like this:
config.Routes.MapHttpRoute("ActionBased", "{controller}/{action}");
to distinguish between the two actions when you POST.

Related

IHM comunication with Api for CQRS+ES

I started to develp a new project with CQRS/ES. As I understand, one command raised a new event. So, I developped a web api with one action mapped to one command.
List of api action :
[Route("api/user/create"), HttpPost]
public Task<IActionResult> Handle(Commands.Create command)
=> HandleCommand(command);
[Route("api/user/update/name"), HttpPost]
public Task<IActionResult> Handle(Commands.UpdateName command)
=> HandleCommand(command);
In my IHM project developped with Blazor, how to communicate with the web api ?
Foreach change in a textbox, i send a http post ?
it's not really a best solution.
I prefer to add a submit button and send one http post. For this solution, how do I communicate all of user's action to web api ?
I would strongly suggest you to take a look at concepts like DDD. The first thing you have to do is get a clear understanding of your Domain.
Let's say that you're working on a Product Inventory system. In your Blazor app you might well have a "create product" page, containing a form with all the relevant fields (eg. "title", "description", "price" and so on).
The backend would expose a POST endpoint /products accepting a CreateProductDTO (check what a DTO is if you're unsure). The DTO would then be mapped into an immutable command, which will then get sent to the relative handler.
The idea is not to send every single user interaction to the server. You have to make a map of the possible actions exposed by your Domain and work your way up.

How can I validate a URL before the request gets to the controller

Our service uses ASP.NET Core and in the application pipeline, we have several middlewares which are configured in StartUp.cs Configure(IApplicationBuilder app) method.
The middlewares are added by this method:
app.UseMiddleware<Type>();
I would like to validate the HttpContext.Request.Path and make sure it can hit one of the controllers. How can I get the list of available routes (controller path) in the middleware code or is there even a simpler way to see if this certain request path will hit one of the registered controller? We used xxxxcontroller : ControllerBase and a [Route("controller/{version}/{id}] attribute to register the controller.
Thanks a lot.
I suggest you to take a look at Asp.net core identity, If I understood what you`re looking for, you need to use roles to guarantee access to certain routes.
I don't know how to get a list of all routes and check that the path is for a valid route but you can use middleware to check the response status code after MVC runs and if the status code is a 404 then you know it wasn't a valid route and you can handle it accordingly.
The UseStatusCodePagesWithReExecute extension method basically uses this approach to handle not only 404 errors but all error status codes.

Route Aliases in ASP.NET Web API 2

I have a Web API that allows users to access/manipulate resources that "belong" to other users. It contains many routes similar to this:
/users/{userId}/resource
I'd like a corresponding set of routes that do the same on behalf of the currently authenticated user:
/resource
Ideally I'd like to get the second set of routes working without doubling the number of actions in my controllers, but I'm struggling to find the right hook. Ideally, I'd like to add a MessageHandler (or something) that intercepts each request, checks if it matches a route, and if it doesn't, prepends "users/" + ID of the authenticated user to the route and checks again. What is the best way to accomplish this?
One constraint: I'm using attribute routing to implement the first set of routes and would ideally like to pull this off without sacraficing that.
The hook is the action selector, as you can see here: Routing and Action Selection in ASP.NET Web API.
You can implement your own action selector to achieve what you want. Here is a sample on how to do that: Magical Web API action selector. From the same page:
We will create a class that implements IActionSelector, as that would allow us to plug into the hook provided by the Web API under GlobalConfiguration.Configuration.Services.

What code is responding when WebAPI responds to a request such as http://server/vroot/odata?

What specifically in WebAPI responds to:
1. http://server/vroot/odata
2. http://server/vroot/odata?$metadata
3. http://server/vroot/odata/Foo
When #3 is requested, I understand that my 'FooController' responds as
configured in my WebApiConfig.cs.
But it is not clear to me how WebAPI responds to #1 or #2. How does it know
what to return? How is that response configured in my code?
UPDATE: Here is a HUGE clue
From http://blogs.msdn.com/b/webdev/archive/2013/01/29/getting-started-with-asp-net-webapi-odata-in-3-simple-steps.aspx
One important thing to realize here is that the controller name, the
action names, and the parameter names all matter. OData controller and
action selection work a little differently than they do in Web API.
Instead of being based on route parameters, OData controller and
action selection is based on the OData meaning of the request URI. So
for example if you made a request for
http://my.server.com/vroot/odata/$metadata, the request would actually get
dispatched to a separate special controller that returns the metadata
document for the OData service. Notice how the controller name also
matches the entity set name we defined previously. I’ll try to go into
more depth about OData routing in a future blog post.
]
returns you the Service Document
returns you the Service Metadata Document
WebAPI knows this because you add a route similar to config.Routes.MapODataRoute("ODataRoute", "odata", model);
Check out this detailed explanation: http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/creating-an-odata-endpoint

Can not access IHttpRequest within ServiceStack Mvc Application

Sorry for my lack of understanding regarding the web stack but this has been haunting me for a couple days.
I am trying figure out how to access Request as a IHttpRequest within the web controllers of the https://github.com/ServiceStack/SocialBootstrapApi example.
It is currently a MVC3 app with ServiceStack's MVC PowerPack. My request always resolves to a System.Web.HttpRequest. I created an extension method on IHttpRequest to check if the current request is coming from a mobile device but it never gets picked up because all my requests are System.Web.HttpRequests instead of a ServiceStack.ServiceHost.IHttpRequest. any help would be great!
You can do something like
var httpReq = System.Web.HttpContext.Current.ToRequestContext().Get<IHttpRequest>();
to turn the request from System.Web.HttpRequest into a ServiceStack.ServiceHost.IHttpRequest.
The requests going into the Controllers of the SocialBootstrapApi examples don't come through the 'ServiceStack pipeline'. The Controllers do inherit from ServiceStackConroller but I think its purpose is to share Session data between MVC and ServiceStack. The ServiceStackContoller doesn't take over the request/response like a request going into the /api path which is handled entirely by ServiceStack in the example project.

Categories