Attribute routing in MVC 5 and optional defaults - asp.net-mvc-routing

Traditional routing defaults meant we were able to access these URLs and always end up on the same action:
/
/Home
/Home/Index
But today we would be writing something in these lines:
[RoutePrefix("Home")]
[Route("{action=Index}")]
public class HomeController
{
public ActionResult Index() {}
public ActionResult ...
}
But this routing definition is by no means the same.
/ (fails)
/Home (works)
/Home/Index (works)
So if we then change upper code to
[RoutePrefix("Home")]
[Route("{action=Index}")]
public class HomeController
{
[Route("~/")]
public ActionResult Index() {}
public ActionResult ...
}
But then we turn the processing upside down:
/ (works)
/Home (fails)
/Home/Index (fails)
We could make declarative code more verbose and make it work as the old-fashioned routing mechanism by:
[RoutePrefix("Home")]
[Route("{action=Index}")]
public class HomeController
{
[Route("~/")]
[Route("~/Home")]
[Route("~/Home/Index")]
public ActionResult Index() {}
public ActionResult ...
}
This works with all three different routes.
Question
This issue is of course bound to the very application default action that defaults controller and action. It's just that I wonder whether this is the only way of doing it? Is there any less verbose code way of getting it to work as expected?

Yeah, right..what you have is the way to do here...
I modified the code a bit here:
[RoutePrefix("Home")]
[Route("{action}")]
public class HomeController
{
[Route("~/")] // GET /
[Route] // GET /Home
[Route("Index")] // GET /Home/Index
public ActionResult Index() {}
public ActionResult ...
}
Some details:
1. Your first case is not exactly the same as conventional routing as in this case you have a literal segment Home which is not similar to the conventional routing optional of {controller}/{action}/{id} and controller = Home, action=Index,id=optional.
2. Your second case is expected as by design if a Route attribute is used on action the attributes on Controller do not take effect.

right now for SEO you should use canonical url meaning single url something like this
public class HomeController
{
[Route("~/")] // GET /
public ActionResult Index() {}
public ActionResult ...
}
so home controller is accessible at root only

Related

Disposal and injecting DbContexts with .NET Core

I know that one way to use a context is via the using statement.
I use it like so within my controllers
[ApiController]
public class MyController : ControllerBase
{
[HttpPost]
public ActionResult PostActionHere(ActionRequestClass request)
{
using (var context = new MyEntityFrameworkContext())
{
....
// use context here
context.SaveChanges()
....
}
}
}
I would like to start injecting it into my controller. Mainly because I think it is easier to read and is more uniform with .NET Core dependency injection.
[ApiController]
public class MyController : ControllerBase
{
private MyEntityFrameworkContext _myDb;
public MyController(MyEntityFrameworkContext myDb)
{
_myDb = myDb;
}
[HttpPost]
public ActionResult PostActionHere(ActionRequestClass request)
{
....
// use context here
_myDb.SaveChanges()
....
}
}
Within my startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyEntityFrameworkContext >(options =>
options.UseSqlServer(Configuration.GetConnectionString("MyEntityFrameworkDatabase")));
}
What I am worried about is that injecting it I lose the disposal properties that come with the using statement. Is that true? Feel free to suggest alternate approaches.
injecting it I lose the disposal properties that come with the using statement. Is that true?
No:
The AddDbContext extension method registers DbContext types with a
scoped lifetime by default.
Configuring a DbContext
And when the scope (here the HttpRequest) ends, the Scoped Lifetime object will be Disposed.

Route attribute with wildcard on the left

I want to be able to automatically match routes that may or may not have a prefix on the left of the incoming request's route.
For example, for this controller
[MyRoutePrefix("api/hello-world")]
public class MyController
{
[Route("")]
public IHttpActionResult Get(){ return OK(); }
}
I'd like the following requests to be matched up with MyController:
http://example.com/api/hello-world
http://example.com/us/api/hello-world
http://example.com/any-word/api/hello-world
Thanks.

Wrapping Spring Data JPA with ApsectJ

Is it possible?
Currently I am using some aspects for my MVC controllers, what works really fine. I'm wrapping their responses and I have desired effect.
I also want to do this with Spring Data JPA repositories. But since they're generated based on the interface e.g:
public interface SomeRepository<T extends Some, ID extends Serializable> extends
BaseRepository<T, ID>, JpaSpecificationExecutor<T> {
public List<T> findById(Long id)
}
It generates me controller which is ready to use:
http://localhost:8080/findById?id=1234
I also want to wrap this controller. Is it possible?
This should work:
#Component
#Aspect
public class MyAdvice {
#Before("execution(* com.company.jpa.SomeRepository+.findById(..))")
public void intercept() { ... }
}
Basically, we are telling the framework to intercept the call to the findById method on any sub-class of SomeRepository.
Here is a sample application demonstrating this in action.

spring mvc request mapping inheritance

I have a Spring MVC 3.2 app and I am trying to find the best way to handle my URLs. I am looking to support multiple customers with something like this:
www.myproduct.com/customerNameX/products
www.myproduct.com/customerNameX/office/
www.myproduct.com/customerNamex/financial
www.myproduct.com/customerNamex/...
I would like to have a controller for each of the path after customerName. I was hoping there was a way to do some sort of inheritance request mapping in Spring MVC. Here is my current attempt that results in deploy errors("Ambiguous mapping found. Cannot map 'rootController' bean method ")
#Controller
#RequestMapping( "/{officeId}/" )
public class RootController {
public #ResponseBody
Office getOffice( #PathVariable String officeId ) {
return offficeService.findOfficeByName(officeId);
}
}
#Controller
#RequestMapping( "/{officeId}/products" )
public class ProductsController extends RootController {
...
}
#Controller
#RequestMapping( "/{officeId}/office" )
public class OfficeController extends RootController {
...
}
The thought being that the root controller would get the first level requests, and the officeId would tell all other requests what officeId is being requests. But I don't think this is the correct approach.
I would really appreciate any tips on the best way to build my URL's properly.

ASP.NET MVC 2 A problem with OnActionExecuting method

I have a controller called "SomeController". I want to check if the user is logged in or if has persissions to execute any action in that controller. To do so, I read that article http://blog.wekeroad.com/blog/aspnet-mvc-securing-your-controller-actions/ and I've written my own class (a test):
public class BaseFilter : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
{
FormsAuthentication.RedirectToLoginPage();
}
//here will be checking the user permissions if he's logged in
}
}
[BaseFilter]
public class SomeController : BaseController
{
...
}
but as You can understand it makes an infinitive loop when I want to run any action from that controller. So, how to cope with that ?
You can apply the action filter on the relevant methods instead of at the class level.
Personally I would name this something like Authorize and then apply it to the controller methods that require authorization.
[Authorize]
public ActionResult Index()
{
// Do stuff
}