In my application there's the need of passing out a specific parameter, when it exists, through all pages.
What is the best way of I can do this?
There's some function that is called whenever I do an GET or POST requisition, in which I can verify if the parameter exist and persist it?
Create an action filter like the one below.
public sealed class ScaffoldActionFilter : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
var model = filterContext.Controller.ViewData.Model as PageModelBase;
// Whatever you want to do.
model.myParam = "Im available in all views";
}
}
Next register it to run on every request. Look in app_start/filterconfig.cs
and and it like this.
filters.Add(new ScaffoldActionFilter());
Now just return the standard pagebasemodel or a derived type from every view and you have what you want.
Related
I am using options pattern that stores different configurations, including API keys for different environments. So far I have been using it fine and injecting my values into classes as needed.
However, I faced a little challenge while trying to setup authorization in the controller and run validation against my ApiKey that is unique per environment, because I was not able to inject IOptions into ApiKeyAuthorizeAttribute class to perform validation.
Here is how my controller looks like now:
[ApiKeyAuthorize]
public class NotificationSettingsController : Controller
{
//some endpoints here
}
ApiKeyAuthorize Class:
public class ApiKeyAuthorizeAttribute : Attribute, IAuthorizationFilter
{
//////This...
private readonly IOptions<MyConfig> _config;
public ApiKeyAuthorizeAttribute(IOptions<MyConfig> config)
{
_config = config;
}
/////////...is what I am trying to accomplish
public void OnAuthorization(AuthorizationFilterContext context)
{
var request = context.HttpContext.Request;
var foundApiKeys = request.Headers.TryGetValue("ReplaceWithOptionsApiKeyName", out var requestApiKeys);
if (!foundApiKeys || requestApiKeys[0] != "ReplaceWithOptionsApiKeyValue")
{
context.Result = new UnauthorizedResult();
}
}
}
My problem is that injecting here isn't possible, but I need to get a value from IOptions<> to run ApiKey validation.
Attributes are constructed in-place, so it's not possible to inject dependencies into them. However, ASP.NET Core provides a workaround. Instead of applying the attribute directly, you can use the ServiceFilter attribute instead and pass it the type of the filter you want to apply:
[ServiceFilter(typeof(ApiAuthorizeAttribute))]
This will dynamically apply the filter to the controller/action while instantiating it with any dependencies it requires at the same time. However, it does limit you in the other direction. For example, if you need to do something like:
[ApiAuthorizeAttribute(Roles = "Admin")]
It would not be possible to achieve this with the ServiceFilter attribute, because you cannot pass property values, like Roles here, along with the type.
My Web API receives a param object consisting of (DateTime) dateFrom, (DateTime) dateTo.
Currently I preprocess the parameter inside my API entry function, which, is repetitive throughout the API.
I wish I could access and modify the parameter before it enters the API entry function.
So I have the action filter below:
public class MyActionParamFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
// pre-processing
object param;
object param2;
actionContext.Request.Properties.TryGetValue("dateFrom", out param);
actionContext.ActionArguments.TryGetValue("dateFrom", out param2);
}
}
From the image, it is clearly that i have passed the parameters to the API. But I have no idea why param and param2 are null...
Is it possible to achieve that?
Finally I follow the answer here:
Change webapi controller action parameter in delegatinghandler
Technically, it is to modify actionContext.ActionArguments.
But I am not too sure if this is 'Best practice' or something.. Let me know your thought if you think i am in the wrong direction of design.
I have a service that I initialize on controller's contructor.
I want to pass UserName(this is my model's property) to this service while instantiating the service on contructor.
First question is, is it possible to get model on controller contructor? I tried but couldn't find any way to do this.
If not then the other way I thought of is to have a common function that will be called everytime any view action is executed, where I can access FormCollection and assign it to the service.
For this I tried overriding few controller's method like Initialize, OnExecuting etc. But I couldn't find form collection in them.
Is there any way to achieve this?
Edit
Some more description
private IService _service;
public HomeController()
{
_service = new ServiceImplementation(/*I want to pass UserName here*/);
}
public ActionResult Submit(MyModel model)
{
_service.UserName = model.UserName;
/* This UserName assignment part I want to centralize,
somewhere in the constructor or in any common event,
so that this will be initialized before any action method is called */
...
...
}
public ActionResult Delete(MyModel model)
{
_service.UserName = model.UserName;
...
...
}
I am rewriting an ASP.NET webforms app in MVC4 and was wondering how to solve the following problem. It is a multi-tenant app, so part of the URL has the tenant NAME in it:
http://mysite/tenant/controller/action
But tenant is an abbreviation representing the tenant, but I'd like to always convert that to the corresponding integer id and use that throughout the code. What is the best way to write that convert code once and have some variable/property available to all controller methods.
public class DivisionController : Controller
{
//
// GET: /Division/
public ActionResult Index()
{
// I want this.TenantId to be available in all controller methods
FetchDivisions(this.TenantId);
return View();
}
Is a base controller the best way to handle this or filters or attributes?
Yes a base controller will handle this just fine. If you need to perform a database lookup to convert the abbreviation to the integer value you can use the OnActionExecuting event like so:
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
base.OnActionExecuting(filterContext);
// Lookup code here.
}
I'm trying to use the new MVC4 DbDataController to expose a restful data api.
My problem is trying to secure this. I have created custom authorization attributes that derive from Authorize Attribute
public class AdminOnlyAttribute : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (!IsAllowed()) {
filterContext.Result = new HttpUnauthorizedResult("Not logged in");
}
...
}
And that works fine when applied to my normal controller actions. I'm trying to use the same thing in my data service like this:
[AdminOnlyAttribute]
public class DataServiceController : DbDataController<AppBuilderDataContext>
{
[AdminOnlyAttribute]
public IQueryable<Thing> GetThings()
{
return DbContext.AllMyThings();
}
}
You can see I've tried my attribute on both the controller and the action, but it's not firing for either one. I've set a breakpoint inside my authorize attribute function, and it's not getting called.
I'm pretty sure Scott Guthrie said this was going to work. Am I doing it wrong, or do I need a completely different method to secure these?
To work with an DataController or any other type derived from ApiController your attribute must derive from System.Web.Http.AuthorizeAttribute