Owin.Testing.TestServer and attribute based routing - c#

We are having the webservice that is using attribute based routing. Few examples of routes:
/api/v1/reporting/client
/api/v1/reporting/client/{id}
/api/v1/reporting/client/{id}/address/{addressId}
/api/v1/reporting/account
/api/v1/billing/client
/api/v1/billing/client/{id}
/api/v1/billing/client/{id}/transactions
Because of this structure we are using attribute based routing (each controller has RoutePrefix attribute and each method on it has Route attribute). At some point we started to convert it OWIN. Also we would like to use have a unit tests for most of our endpoints. So I ended up trying to use Microsoft.Owin.Testing.TestServer. However any endpoint I'm trying to test I'm getting 404 and it looks like b/c we are using attributes for routing (when I tested this method on webapi that doesn't use attributes I do not have this issue). So my question is how can I make attribute based routing work with TestServer or how I can replace attributes with something else that will work with TestServer and provide me routes I listed earlier.

Related

Rewrite URl according to Attribute

We have an ASP.NET Core Web API running on .NET 5. It has got many controllers and routes that are sometimes protected via the Authorize attribute and sometimes they are public.
[ApiController]
[Route("[controller]")]
public class UserController : ControllerBase {
[HttpGet("me")]
public IActionResult GetMyPublicInformation()
{
// code...
}
[HttpGet("me")]
[Authorize]
public IActionResult GetMyPrivateInformation()
{
// code...
}
}
Well now I would like to publish these REST routes through different HTTP Routes, depending on the Authorization requirement. For example, the route GetPublicInformation does not require authorization. That route should be available under public/user/me. Whereas the method GetMyPrivateInformation does require authorization and should be published under the route secure/user/me.
Of coure, I am aware that I can define the route manually in the HttpGet attribute (i.e. [HttpGet("public/user/me")), but - besides that I'm lazy - it would be error prone because we have the information available twice: Once with in the manual route definition (HttpGet) and once in the Authorize attribute. So if someone forgets to change one of the two attributes, we get an inconsistency.
Question: What are my options to automate this URL rewriting (I'm thinking of middleware)? Are there any drawbacks you see using this approach? I have been fighting this idea because I don't like extra magic sauce in my codebase. I prefer explicity, that's why I'm going for the manual route naming right now...
By the way: I have to take this on me because of limitations in Microsoft's MSAL library. I believe I shouldn't have to do this because we host an OpenAPI definition on which routes are and which routes aren't authorized. That should be enough in most cases.

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.

MVC core routing not functioning as expected

So it's my first time setting up an netcore MVC based application. I've used MVC 4 in the past on plain old asp.net.
So i'm having issues with my routing. My application is an single page application (spa) that is accessible from the home controller on the index action. I can access this controller method fine, and my defaults are set so that this is navigated to at route: /.
I also have a second controller for authentication called AccountController. This controller's methods take and return JSON, rather then views. I can also access the methods on this controller from my application.
The issue i'm having lies in my next controller, which is the start of my API.
As such, i've put it in a folder called api inside my controllers folder. However, no matter what i try, i cannot seem to get the methods on the controller accessible. I have also tried moving it out of the api folder and just having in the route of the controllers folder.
The routing deffinition
app.UseMvc(routes =>
{
routes.MapRoute(
name: "api",
template: "api/{controller=Core}/{id?}");
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
I've tried adding and removing the api definition, removing the api part, and adding a template for actions aswel, all to no effect.
The troublesome controller
public class CoreController : Controller
{
[HttpGet]
public JsonResult Get()
{
return Json("Dev");
}
}
I've tried adding [Route(~routing here~)] annotations to this controller and its methods with no success either.
Folder structure
I should also mention that i've tried plenty of URL's to access this controller on:
/api/Core/
/Core/
/api/Core/Get
I've been wracking my brain for the best part of a day trying to get this sorted and i know i'm missing something obvious, i just can't for the life of me work out what it is.
Edit:
I've added a cut-down sample of my project to github at: https://github.com/lexwebb/aspnet-test if anyone would like a complete example
Edit 2
It appears that my example works, i'm going to add things in to see what breaks it
AFAIK, default route requires the {action} using as well.
Instead of "api" default routing, you may to use the following configuration for such type of controllers (RESTFul controller):
[Route("api/[controller]")]
public class CoreController : Controller
{
[HttpGet]
public JsonResult Get()
{
return Json("Dev");
}
}
I found this Routing is ASP.NET Core article useful in the past.
So as it turns out, i had made a mistake in a totally unrelated place. I had renamed my project half way through the beginning stage of development, after i had build scripts in place. This led to the the wrong dll being referenced on the server when the code was ran, a version that had all of my routing EXCEPT the new one, of course.

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.

Mvc 5 Attribute Routing

I am trying to use the build-in attribute routing that comes with Mvc 5, previously I was using the AttributeRouting package on Nuget.
But how do i set up routes by specifying whether it is for a Get or Post request?
In AttributeRouting there was GET() and POST() attributes, but in Mvc 5 there is only a Route() Attribute?
You can still use the PostAttribute in MVC5, it's fully supported.
"The earlier style of routing, called convention-based routing, is
still fully supported. In fact, you can combine both techniques in the
same project."
source

Categories