Fluent Security - configuring parameterized controller actions - c#

I have done quite a bit of research and have tested both the 1.4 and 2.0 versions of the FluentSecurity libraries and I don't seem to be able to use the configuration pattern:
configuration.For<MyController>(x => x.GetCustomer())
.RequireRole(appRoles);
when my controller action requires a parameter such as:
public ActionResult GetCustomer(int customerID)
Is this type of configuration currently supported? If so, how do I implement a role requirement against an action that has a required parameter?

I was asking the same question. Currently, you can pass in default values for the parameters.
configuration
.For<HomeController>(x => x.Index(default(string)))
.DenyAnonymousAccess();
where HomeController is:
public ActionResult Index(string id)
{
return View();
}

Related

Questions about routing in Asp.net Core MVC 2

I can't wrap my mind around the routing mechanism in asp.net core MVC 2.
Here's what I have:
I already built a functioning page to add 'Materials' to a 'Application'.
The URL to call this page is:
http://localhost:33333/AddMaterial/Index/57
which uses the default route:
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}"
);
Whereby 57 is the application id, so that I know what 'Application' gets the new 'Material'. The Index Method in the controller looks like this, and works like expected:
[HttpGet] public IActionResult Index(string id)
{
var model = GetModel(context, int.Parse(id));
return View("Index", model);
}
So far so good... Now here's my problem:
I want to use the same controller and view to also edit 'Materials'. But for that i'd need two parameters in Index(). I'd need:
string applicationId
string materialId
as parameters.
So I added a new route:
routes.MapRoute(
name: "whatImTryingToAchieve",
template: "{controller}/{action}/{applicationId?}/{materialId?}"
);
And of course I updated the controller:
public IActionResult Index(string applicationiId, string materialId)
{
// Do stuff with materialId etc.
// ...
return View("Index", model);
}
I know that the routing system has a specific order. So I tried defining my new route before the default route. That didn't work.
I then tried to put it after the default route, which didn't work either.
I read through a lot of information about the routing system, but I didn't seem to find the answer to my simple question:
How can I add another, specific route?
Help would be much appreciated :)
EDIT: Attribute based routing as suggested by Igors Ĺ utovs
Controller:
[Authorize(Roles = "Admins")]
[Route("AddMaterial")]
public class AddMaterialController : Controller
{
//....
[Route("AddMaterial/{applicationId}/{otherid}")] // Nope. Nothing.
[HttpGet] public IActionResult Index(string applicationId, string otherid)
{
return View();
}
[Route("AddMaterial/Index/{applicationId}")] // Didn't work.
[Route("AddMaterial/{applicationId}")] // Didn't work either...
[HttpGet] public IActionResult Index(string applicationId)
{
return View();
}
}
So much for Attribute base routing.
I will provide my subjective opinion on the essence of the described problem. It seems that the question could be rephrased as: "What is the correct ASP.NET Core way to design routes and resolve such situations with multiple parameters?"
TLDR: use Attribute-Based Routing
This is the new type of routing which was added in ASP.MVC 5. Since then the old routing mechanism has been regarded as "Conventional-Based". ASP.NET Core currently allows mixing of both. I will provide a detailed example of how to solve the described problem using the Attribute-Based Routing only because the new approach provides the following advantages:
Route information is moved closer to controller actions, hence code is easier to understand and troubleshoot
Controller names and their method are decoupled from route names
Moving on to the solution. Let's assume that we have 2 models: Application and Material. I would create 2 distinct controllers to manage each. From your example, I understand that the relationship between these domain entities is one-to-many e.g. one Application could have many Materials. This suggests the following routes:
GET: applications/{applicationId}
GET: applications/{applicationId}/materials/{materialId}
...with a look back at principles of Restful Routing.
The ApplicationController would then look like this:
[Route("applications")]
public class ApplicationController
{
[HttpGet("{applicationId}")]
public IActionResult Index(string applicationId)
{
// return your view
}
}
While the MaterialController would look like this:
[Route("applications/{applicationId}/materials")]
public class MaterialController
{
[HttpGet("{materialId}")]
public IActionResult Index(string applicationId, string materialId)
{
// return your view
}
}
The call to UseMvc(..) extension method in Configure method of Startup.cs can now be simplified to just:
app.UseMvc();
Hope you'll find it useful!

Edit View in asp.net mvc - controller error

I'm writing web service in asp.net mvc and still having the same error connected with the code below:
public ActionResult Edit(int C)
{
var customers = _ourCustomerRespository.GetCustomers();
var std = customers.Where(s => s.CustomerID == C).FirstOrDefault();
return View(std);
}
[System.Web.Http.HttpPost]
public ActionResult Edit(Customer C)
{
return RedirectToAction("Index");
}
and when i try use my service i have error message
The current request for action 'Edit' on controller type
'DefaultController' is ambiguous between the following action methods:
System.Web.Mvc.ActionResult Edit(Int32) on type
WebApplication2.Controllers.DefaultController
System.Web.Mvc.ActionResult Edit(WebApplication2.Models.Customer) on
type WebApplication2.Controllers.DefaultController
Can anybody help me with solving that?
That's because you decorated your controller action with the wrong HttpPost attribute. You need this one:
[System.Web.Mvc.HttpPost]
public ActionResult Edit(Customer C)
The one you have used (System.Web.Http.HttpPost) is designed for ASP.NET Web API actions and has strictly zero effect when placed on an ASP.NET MVC controller action. So the ASP.NET MVC framework cannot disambiguate between the 2 Edit actions because they are using the same verb and thus you are getting the error.
Remark: please make sure that you tag your question correctly to avoid any confusions. Currently you have used the asp.net-web-api whereas the controller action you have shown is clearly asp.net-mvc. Those are 2 completely different frameworks.

Multiple controller types were found error in c# web api 2.0

Why this doesn't work? I get error: System.InvalidOperationException: Multiple controller types were found that match the URL. This can happen if attribute routes on multiple controllers match the requested URL.
public class ConfigUpdateController: ApiController
{
[HttpPut]
[Route("api/device/{serial}/config")]
public IHttpActionResult Update(
[FromUri] string serial,
[FromBody] Configuration configuration)
{
}
}
public class ConfigQueryController: ApiController
{
[HttpGet]
[Route("api/device/{serial}/config")]
public IHttpActionResult Get(
[FromUri] string serial)
{
}
}
The reason why i want to have methods for same resource in separate controllers is decoupling queries from commands.
EDIT
To be honest, it's ample code to illustrate my problem, so please don't bother commenting controllers naming ect. It's not important in context of my question.
EDIT 2
I've found here web-api overview thet routing has 3 phases:
Routing has three main phases:
Matching the URI to a route template.
Selecting a controller.
Selecting an action.
So it seems this does not work because controller can't be resolved and method verb (PUT, GET) are not even checked? O_o
Read the error carefully, then look at your attribute routing. You have identical URLs for two different actions.
Program would have no idea which action to execute.
use [FromRoute] instead of [FromUri] annotations

How to add a .Net MVC request filter to prevent action calls based on role membership?

In .Net MVC5, how would one add a request filter to prevent action calls based on role membership?
See this comment:
wouldn't it make more sense to use a request filter to prevent the
action call on the controller in the event that the current user did
not have the right role membership instead of trying to mix the auth
logic in to the business logic?
Thank you.
My best solution for this is using:
[AuthorizeAttribute]
You can place it as a normal attribute is used in c# mvc, like for ex:
[Authorize]
public ActionResult AuthenticatedUsers()
{
return View();
}
You can also use it in top of the controller like this:
[Authorize]
public class HomeController : Controller
{
}
And if you want it do be depedent on roles, you just simple give one parameter to this attribute like this:
[Authorize(Roles = "Admin, Super User")]
public ActionResult AdministratorsOnly()
{
return View();
}
[Authorize(Users = "Betty, Johnny")]
public ActionResult SpecificUserOnly()
{
return View();
}
Here is some more detailed information for your question which I'd suggest would help you alot.
Good luck!

Access to controller method

I have Controller with some method GET :
public class TestController : ApiController
{
public List<T> Get(){...}
[ActionName("GetById")]
public T Get(int id){...}
}
Can i access second Get method as /Get?id=1 even if i have different ActionName?
ActionName for generating cache with different names
Updated because my previous answer was related to standard MVC controllers not Web API because that is what the ActionName attribute is for. I am not sure what if anything it would do on a web api controller. Without attributes or a change from the deault routing your actions would have the following routes "/api/test/" Get() "/api/test/id" Get(int id) where id is an int.
If you want more flexibility MVC5 supports attribute routing

Categories