I am looking for a way to override action call if some action is present in the controller.
Imagine :
[Route("api/[controller]")]
public partial class UsersController : BaseController {
[HttpGet("Friends/{id}")]
public IActionResult GetFriends(int id) {
// some code
}
then I have in an other file :
[Route("api/[controller]")]
public partial class UsersController : BaseController {
[HttpGet("Friends_custom/{id}")]
public IActionResult GetFriends_custom(int id) {
// some code
}
I want my frontend to only call
/users/friends
How can I get asp route to match the _custom if it exist?
After a long day, I found out we can use Order in the RouteAttribute. it does exactly what I need!
Related
I'm new to ASP Net and I'm having a little trouble passing a URL as a simple parameter.
These are the solutions that I've tried:
[ApiController]
[Route("api/[controller]")]
public class LoginRedditController : ControllerBase
{
[HttpGet("{*longUrl}")]
public ActionResult<string> Get(string longUrl)
{
Console.WriteLine(longUrl);
return "OK";
}
}
This is the URL that I've tried to call:
http://localhost:5001/LoginReddit?longUrl=https://www.reddit.com/r/playmygame/comments/glftsj/stickn_roll_collect_everything_as_you_roll/
I also tried to encode the URL but the result is the same: I got a "ERR_EMPTY_RESPONSE"
This is my second try:
[ApiController]
[Route("api/[controller]")]
public class LoginRedditController : ControllerBase
{
[HttpGet]
public ActionResult<string> Get([FromQuery]string url)
{
Console.WriteLine(longUrl);
return "OK";
}
}
I used the same URL used before but I got the same result.
In my tried try I changed the Route like this:
[Route("api/[controller]/{url}")]
public class LoginRedditController : ControllerBase
{
[HttpGet]
public ActionResult<string> Get([FromQuery]string url)
{
Console.WriteLine(longUrl);
return "OK";
}
}
And I've tried with the following URL:
http://localhost:5001/LoginReddit/https://www.reddit.com/r/playmygame/comments/glftsj/stickn_roll_collect_everything_as_you_roll/
Also encoded but I got the same resoult.
Where is the problem guys?
For a URL like this:
http://localhost:5001/LoginReddit?longUrl=https://www.reddit.com/…
You would write your controller action like this:
[ApiController]
[Route("[controller]")]
public class LoginRedditController : ControllerBase
{
[HttpGet]
public ActionResult<string> Get(string longUrl)
{
Console.WriteLine(longUrl);
return "OK";
}
}
The longUrl string value is automatically taken from the query arguments passed to the route. And the route for the action is combined from that [Route] attribute on the controller and the [HttpGet] attribute on the action.
The Route Attribute specified the format of the url. You missed the "api" part in your url, and it should be like this:
http://localhost:5001/api/LoginReddit?longUrl=https://www.reddit.com/r/playmygame/comments/glftsj/stickn_roll_collect_everything_as_you_roll/
[ApiController]
[Route("api/[controller]")]
public class LoginRedditController : ControllerBase
{
[HttpGet]
public ActionResult<string> Get([FromQuery]string url)
{
Console.WriteLine(longUrl);
return "OK";
}
}
I have a class library and having a set of API Controllers in this class library.
There is a set of .NET Core Microservices that use this class library and if they want can override the Controller Action Methods in their implementation.
Base Controller:
[ApiController]
[Route("[controller]")]
public class BaseController : Controller
{
[HttpGet]
public virtual string Get()
{
return "From Base class";
}
}
Child Controller:
public class ChildController: BaseController
{
[HttpGet]
public override string Get()
{
return "From Child class";
}
}
Now my question is, if I browse "http://localhost:60634/base", then it should hit Child Controller Get API instead of Base controller Get API.
I thought of using redirection routing but did not find any such blog for .NET Core Microservice.
Please help.
public class BaseController : Controller
{
public virtual string HealthCheck()
{
return "From Base class";
}
}
[ApiController]
[Route("Base")]
public class ChildController : BaseController
{
[HttpGet]
public override string HealthCheck()
{
return "From Child class";
}
}
You can use something like this:
[ApiController]
public class BaseController : ControllerBase
{
[Route("~/Base/Get")]
public virtual string Get()
{
return "From Base class";
}
}
[ApiController]
public class ChildController : BaseController
{
[Route("~/Child/Get")]
public override string Get()
{
return "From Child class";
}
}
So what I have is a base controller that the following [Route] definition
[Route("{application}/api/[controller]")]
public class BaseController
{
}
All of my current controllers inherit from BaseController.
What I am trying to achieve is that two different application can call my controllers and my code to be aware of what 'application' is calling it.
Application 1 should be able to call /Application1/Api/MyController
Application 2 should be able to call /Application2/Api/MyController
and both requests should go to the same controller but my code should be aware of which application called it.
I thought about having some sort of Middleware and then work out the application from the Request.Path, and then store it in something like HttpContext.Current.Items but that doesn't seem like the correct way to do it.
My personal preference here would be to pass the value as an HTTP header rather than a route parameter, especially if you want it everywhere. It means you don't need a Route attribute and a different URL per application. Using a custom ActionFilterAttribute, there's a bunch of ways you can pass this detail into your action. For example:
public class ApplicationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.HttpContext.Request.Headers.TryGetValue("Application", out var values))
{
// Method 1: This allows you to specify a parameter on your action
context.ActionArguments.Add("application", values.First());
// Method 2: This adds the value into the route data
context.RouteData.Values.Add("Application", values.First());
// Method 3: This will set a property on your controller
if (context.Controller is BaseApplicationController baseController)
{
baseController.Application = values.First();
}
}
base.OnActionExecuting(context);
}
}
And apply it to action methods or your controller:
[Application]
public class FooController : Controller
{
}
Method 1 Usage:
public IActionResult Index(string application)
{
// do something with the parameter passed in
}
Method 2 Usage:
public IActionResult Index(string application)
{
var application = (string)RouteData.Values["Application"];
}
Method 3 Usage:
First, create a base controller that contains the property:
public abstract class BaseApplicationController : Controller
{
public string Application { get; set; }
}
Then make sure your controller inherits from it:
[Application]
public class FooController : BaseApplicationController
{
}
Now you can access the property on your controller:
public IActionResult Index(string application)
{
var application = this.Application;
}
Bonus Method 4:
As an aside, you could use this method to use the URL route value, using the base controller from method 3, modify the attribute to look like this:
public class ApplicationAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext context)
{
if (context.Controller is BaseApplicationController baseController)
{
baseController.Application = (string)context.RouteData.Values["application"];
}
base.OnActionExecuting(context);
}
}
Add a route attribute to your controller:
[Route("{application}/api/[controller]/[action]")]
And now you should have the property value on the controller set.
You could move the route template into action and then each action would technically be aware of its caller context by your proposed convention:
[Route("api/[controller]")]
public class YourController : BaseController
{
[HttpGet("{application}")]
public IActionResult Get(string application)
{
if (application == "Application1")
{
...Application1 called
}
if (application == "Application2")
{
...Application2 called
}
...
}
}
Of course, this is your proposed convention and it is not enforced through some custom application authentication in any way so you will have to trust that your callers will correctly identify themselves through this convention.
Another approach, could be to have a base class variable and set that after inspecting the route.
[Route("{application}/api/[controller]")
public class BaseController: Controller
{
protected string CallingApp { get; set; }
public override void OnActionExecuting(ActionExecutingContext ctx)
{
CallingApp = ctx.RouteData.Values["application"];
base.OnActionExecuting(ctx);
}
}
Can anybody help me with this link?
[Route("api/[controller]")]
public class AuthController : ControllerBase
{
private readonly IAuthService _auth;
public AuthController(IAuthService auth)
{
_auth = auth;
}
[HttpGet("getuser/{sessionGuid}")]
public IActionResult Get(Guid sessionGuid)
{
\\code
}
How should the URL be written in order to get to public IActionResult Get(Guid sessionGuid)?
The Route("api/[controller]") attribute you have given your Controller tells the framework to use the name of the Controller as part of the route.
In this case you have an AuthController so all the routes in this Controller will be prefixed with api/auth/.
Additionally you've specified to the framework to map you Get method to the "getuser/{sessionGuid}" route (where sessionGuid is some Guid).
Putting this together the URL you need to call is api/auth/getuser/{sessionGuid}.
All of this needs to be prefixed by the hostname etc. http://localhost:5000/ for example.
Move your route onto the function, and configure it however you'd like.
In my example, it would be: HTTP GET : http://api.com/my/ur/with/as/many/slashses/as/I/want/52
public class AuthController : ControllerBase
{
private readonly IAuthService _auth;
public AuthController(IAuthService auth)
{
_auth = auth;
}
[Route("my/url/with/as/many/slashes/as/I/want/{sessionGuid}")]
[HttpGet("{sessionGuid}")]
public IActionResult Get(Guid sessionGuid)
{
\\code
}
}
I have below route URL:-
www.domanname.com/subroute/GetInfo?param1=somestring¶m2=somestring
I have function in webapi as:-
public class HomeController : ApiController
{
public object GetInfo(string param1,string param2)
{}
}
To apply route:-
[RoutePrefix("subroute")]
public class HomeController : ApiController
{
[Route("GetInfo?param1={param1:string}¶m2={param2:string}")]
public object GetInfo(string param1,string param2)
{}
}
But after applying above URL:-
www.domanname.com/subroute/GetInfo?param1=somestring¶m2=somestring
It is not able to find that URL
How can I design this particular route?
You need to modify the routes a bit as query string are not normally used in attribute routes. They tend to be used for inline route parameters.
[RoutePrefix("subroute")]
public class HomeController : ApiController {
//Matches GET subroute/GetInfo?param1=somestring¶m2=somestring
[HttpGet]
[Route("GetInfo")]
public IHttpActionResult GetInfo(string param1, string param2) {
//...
}
}
Also
Enabling Attribute Routing
To enable attribute routing, call MapHttpAttributeRoutes during configuration. This extension method is
defined in the System.Web.Http.HttpConfigurationExtensions class.
using System.Web.Http;
namespace WebApplication
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API routes
config.MapHttpAttributeRoutes();
// Other Web API configuration not shown.
}
}
}
Reference Attribute Routing in ASP.NET Web API 2
[RoutePrefix("subroute")]
public class HomeController : ApiController {
[HttpGet]
[Route("GetInfo/{param1}/{param2}")]
public IHttpActionResult GetInfo(string param1, string param2) {
//...
}
}
Calling
//Matches GET subroute/GetInfo/Hello/World