MVC 4 How to process a url parameter on every page, base controller? - asp.net-mvc-4

Looking for some guidance in designing my new MVC 4 app.
I would like to have a url parameter s=2011 on every page of the app to let me know what year of data I'm working with. Obviously, the user will have a way to change that parameter as needed.
I will need that parameter in every controller and wondering the best way to do this. I was thinking of creating a base controller that reads Request.QueryString and puts the year into a public property. However, considering all the extensability points in MVC, I'm wondering if there's a better way to do this?

This very much depends on the design of your app, but just to give you two alternatives
IActionFilter
If you are doing data context per request you can use a global IActionFilter to hook pre-action execution globally and apply a query filter to your data context behind the scenes.
Major down-side of this is that to test the controller you will need to have the full MVC pipeline setup so that the actionfilter gets applied properly.
Dependency Injection
Instead of using sub-classing (base controller as you say) you can use dependency injection . Keeping things more loose will allow you to pull the filter from query string, cookie, user setting in the database or whatever else - without your controller knowing where it comes from.
Here is some pseudo code how I would do it if I was using something like Entity Framework or Nhibernate (also I am sure applicable with other technologies as well)
public Car
{
public string Year { get; set; }
}
public class CarsDataContext : DbContext
{
private IQuerable<Cars> _cars = null;
private Func<Car, bool> _carsFilter = null;
public IQuerable<Car> Cars {
get {
if (_carsFitler != null)
return _cars.Where(_carsFitler);
return _cars;
}
set { _cars = value; }
}
public void ApplyCarsFilter(Func<Car, bool> predicate)
{
_carsFilter = predicate;
}
}
Assuming you have dependency injection setup already (NInject or whichever other framework) in you can configure how the context to be intialized
Bind<CarsDataContext>().ToMethod(() => {
string yearFilter = GetYearFilter(); // can be coming from anywhere
CarsDataContext dataContext = new CarsDataContext();
dataContext.Applyfilter(car => car.Year == yearFilter);
return dataContext;
}).InRequestScope();
Then my controller knows nothing about the data filtering and I can easily test it:
class MyController : Controller
{
public MyController(CarsDataContext dataContext)
{
}
...
}
However I would only do this is filtering the dataset was across many controllers and important part of my software. Otherwise it's pure over-engineering.

Related

Injecting IOptions<> into ApiKeyAuthorizeAttribute

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.

Access to container of Simple Injector MVC views

In a Sitecore project I've integrated Simple Injector using this article
It uses sitecore pipelines and then uses a method in App_start
namespace BBC.App_Start
{
public class SimpleInjector : IPackage
{
public void RegisterServices(Container container)
{
GetContainer.RegisterServices(container);
container.Register(() => new SitecoreContext(), Lifestyle.Scoped);
container.Register(() => new Container(), Lifestyle.Singleton);
}
}
}
Simply I can inject container into controller constructor but can't have container in View files.
I tried to declare a static property in App-start and save container to it. but still I'm getting no registration type in Views
What is the best way to have container object in views?
As Stephen suggests in his comment, the literal answer to your question is "you shouldn't do that - because it's not really the way MVC and DI are supposed to work". The more detailed answer goes something like this:
The job of your view is to present data that it has been passed via the Model. Views should not really contain logic. Very simple stuff like "if flag is false, hide this block of mark-up" is ok, but the more complex code to work out what the value of the flag is shouldn't be in the view.
MVC tries to make our website code better by encouraging you to separate presentation (the View) from data (the Model) and logic (the Controller). This should make our code easier to work with - So if you have processing that needs doing, then it should really be happening when your controller method runs.
If your view requires some special data, best practice suggests it should work it out in the controller method and pass it to the view in the model. The code might look more like this:
public class MyModel
{
public string SpecialData { get; set; }
}
public class MyController : Controller
{
public ActionResult DoSomething()
{
// do whatever processing is needed
var somethingCalculate = resultFromYourOtherObject();
// do other stuff
var model = new MyModel() { SpecialData = somethingCalculated };
return View(model);
}
}
And then the View just needs to accept the MyModel class as its model, and render the SpecialData property - no logic required.
I think also it's considered a bad idea to have calls to fetch objects from your DI container spread about your codebase. For MVC apps, generally your DI container gets wired in to the process of creating a controller for a request when the app starts up. Rather than passing about a DI Container into your controllers, the DI framework extends the Controller-creation process, and the container isn't exposed outside of this. When the MVC runtime needs to create a controller, the controller-creation logic uses the DI framework to fetch objects for all the controller's dependencies.
Without more detail about what you actually want to achieve, it's difficult to say what the "right" approach to creating your object(s) here is, but the two most common patterns are probably:
1) Constructor injection: Your controller has a parameter which accepts the object required. The DI container creates this object for you at the point where it creates the controller, so your controller gets all its dependencies when it is created. Good for: scenarios where you know how to create the object at the beginning of the request.
public interface IMySpecialObject
{
string DoSomething();
}
public class MyController : Controller
{
private IMySpecialObject _specialObject;
public MyController(IMySpecialObject specialObject)
{
_specialObject = specialObject;
}
public ActionResult RenderAView()
{
// do some stuff
var data = _specialObject.DoSomething();
return View(data);
}
}
As long as IMySpecialObject and a concrete implementation for it are registered with your DI container when your app starts up, all is well.
2) Factory classes: Sometimes, however, the object in question might be optional, or it might require data that's not available at controller-creation time to create it. In that case, your DI framework could pass in a Factory object to your controller, and this is used to do the construction of the special object later.
public interface ISpecialFactory
{
ISpecialObject CreateSpecialObject(object data);
}
public class MyController : Controller
{
private IMySpecialFactory _specialFactory;
public MyController(IMySpecialFactory specialFactory)
{
_specialFactory = specialFactory;
}
public ActionResult RenderAView()
{
// do some stuff
if( requireSpecialObject )
{
var data = getSomeData();
var specialObject = _specialFactory.CreateSpecialObject(data);
var data = _specialObject.DoSomething();
return View(data);
}
return View("someOtherView");
}
}
But a good book on using DI may suggest other approaches that fit your specific problem better.

Preventing AllowAnonymous

I have a base controller which is globally marked as [Authorize]. Is there a way to prevent Controllers which inherit it from overriding the authorization requirement by simply adding the [AllowAnonymous] attribute?
Here is my exact scenario: I have three base controllers: one is for anonymous users, and two are for logged in users, both of which are globally decorated with [Authorize]. Each new controller that is created inherits from one of the base three, depending on which functionality is needed. One of the [Authorize] controllers contains "highly secure" functionality which absolutely should not be run by anonymous users. A developer inheriting from this "secure" base controller accidentally decorated some methods with [AllowAnonymous] which enabled anonymous users to potentially access the "secure" functionality in the base controller. It was caught in testing but I thought it would be a good idea to prevent that type of mistake, and I'm wondering if there is a simple way to do that. For now, I have taken all of the code inside of the secure base controller and wrapped it in blocks of:
if (Request.IsAuthenticated)
{
// do stuff
}
else
{
// redirect to login page, basically simulating what [Authorize] does
}
The above accomplishes what I want, however it kind of defeats the purpose of the global [Authorize] decoration in the first place. I'm envisioning something along the lines of:
[Authorize(AllowAnonymousOverride=false)] // this doesn't exist, but might be helpful
Is there a better way to accomplish this functionality?
The correct way to do this is to derive your own AuthorizeAttribute. The default AuthorizeAttribute looks like:
namespace System.Web.Mvc
{
public class AuthorizeAttribute : FilterAttribute, IAuthorizationFilter
{
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
{
throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
}
// This is the Important part..
bool flag = filterContext.ActionDescriptor
.IsDefined(typeof(AllowAnonymousAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor
.IsDefined(typeof(AllowAnonymousAttribute), true);
if (flag)
{
return;
}
if (this.AuthorizeCore(filterContext.HttpContext))
{
HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
cache.SetProxyMaxAge(new TimeSpan(0L));
cache.AddValidationCallback(
new HttpCacheValidateHandler(this.CacheValidateHandler), null);
return;
}
this.HandleUnauthorizedRequest(filterContext);
}
}
}
Derive your own:
public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public bool IsAllowAnonymousEnabled { get; set; }
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (OutputCacheAttribute.IsChildActionCacheActive(filterContext))
{
throw new InvalidOperationException(MvcResources.AuthorizeAttribute_CannotUseWithinChildActionCache);
}
// This is the Important part..
bool flag = IsAllowAnonymousEnabled
&& (filterContext.ActionDescriptor
.IsDefined(typeof(AllowAnonymousAttribute), true)
|| filterContext.ActionDescriptor.ControllerDescriptor
.IsDefined(typeof(AllowAnonymousAttribute), true));
if (flag)
{
return;
}
if (this.AuthorizeCore(filterContext.HttpContext))
{
HttpCachePolicyBase cache = filterContext.HttpContext.Response.Cache;
cache.SetProxyMaxAge(new TimeSpan(0L));
cache.AddValidationCallback(
new HttpCacheValidateHandler(this.CacheValidateHandler), null);
return;
}
this.HandleUnauthorizedRequest(filterContext);
}
}
Usage:
[CustomAuthorizeAttribute(IsAllowAnonymousEnabled = false)]
public class MyController : Controller
{
[AllowAnonymous]
public ActionResult Index()
{
// This will still execute Authorization regardless of [AllowAnonymous]
return View();
}
}
You can't call base.OnAuthorization() because it will Allow AllowAnonymous.
First, you seem to have a controller with some methods and then your approach is to inherit it so that the same methods are exposed. I wonder what's the point of having two or more controllers that expose the same data. Was is the mistake of that developer or rather it is a custom routine in your approach?
Then, you expect to have an attribute that prevents other attributes but this is clearly not possible in the language nor in the mvc framework.
Third, someone wrote a controller without unit tests or maybe with tests but no one verified these tests so that the issue was caught during manual testing phase. This indicates that the issue is wider and not only restricted to inheritance - suppose your developer wrote a controller that doesn't inherit anything and still exposes some critical data because of allow anonymous mark. Then what? Even if you have a remedy for your original issue, it wouldn't be able to catch the new possible issue.
My advice would be to have a custom analyzer attached to the post build event that scans all possible controllers and makes a list of all anonymous and restricted actions and compares it to a previously generated list. If there is a change, then an alert is created and someone has to resolve the issue manually, either by approving newly created actions or rejecting changes because a bug has been introduced.

How to tackle behavior variation with StructureMap?

I have a set of componentes registered to StructureMap. What should be the best way to resolve a component depending on the actual Tenant?
Small example:
There are two tenants, say, Yellow and Green.
I have an IValidator that has two implementations: YellowValidator and GreenValidator.
Say the application is MVC and that the tentant comes form the URL.
So, I just need the proper IValidator to be injected depending on the tenant.
I've seen many solutions for multi-tenant applications that deals only with multitenancy of data, normaly configuring different databases depending on the tenant. That involves only parameter passing. But this is the case where variation occurs in behavior, not in data. I want the IoC container to Resolve the right instance transparently.
EDIT: more info:
The IValidator interface have a simple method bool Validate(), but the implementation require some injection.
There are other custom validators, but they are used by both tenants.
There is a clear tentant strategy based on the URL. This means that each request can have a different tenant, and that a single application serves both tenants.
There are many ways to skin a cat. It's hard for me to guess the design of your application, so here is an idea. Things that come in mind are to hide validators behind a composite, to allow users of the IValidator interface to know nothing about having many implementations. Such composite can look like this:
public class ValidatorComposite : IValidator
{
private IEnumerable<IValidator> validators;
public ValidatorComposite(
IEnumerable<IValidator> validators)
{
this.validators = validators;
}
public bool Validate(object instance)
{
return this.validators.All(v => v.Validate(instance));
}
}
You can create multiple composites and register them by key where the key is the name of the tenant (but without keyed registrations is probably just as easy). Those composites can be wrapped in yet another composite that will delegate to the proper tenant-specific composite. Such a tenant-selecting composite could look like this:
public class TenantValidatorComposite : IValidator
{
private ITenantContext tenantContext;
private IValidator defaultValidator;
private IDictionary<string, IValidator> tenantValidators;
public ValidatorComposite(
ITenantContext tenantContext,
IValidator defaultValidator,
IDictionary<string, IValidator> tenantValidators)
{
this.tenantContext = tenantContext;
this.defaultValidator = defaultValidator;
this.tenantValidators = tenantValidators;
}
public bool Validate(object instance)
{
string name = this.tenantContext.CurrentTenant.Name;
return this.defaultValidator.Validate(instance) &&
this.tenantValidators[name].Validate(instance);
}
}
The ITenantContext is an abstraction that allows you to get the current tenant within the current context. You probably already have something like that in place, but I imagine an implementation to look something like this:
class UrlBasedTenantContext : ITenantContext
{
public Tenant Current
{
get
{
// Naive implementation.
if (HttpContext.Current.Request.Url.Contains("tenant1"))
{
return Tenant1;
}
return Tenant2;
}
}
}
Create a TenantValidatorComposite would be easy:
var defaultValidator = CompositeValidator(
GetAllDefaultValidators());
var tenantValidators = new Dictionary<string, IValidator>()
{
{ "tenant1", new CompositeValidator(GetValidatorsFor("tenant1")) },
{ "tenant2", new CompositeValidator(GetValidatorsFor("tenant2")) },
};
var tenantValidator = new TenantValidatorComposite(
new UrlBasedTenantContext(),
defaultValidator,
tenantValidators);
I hope this helps.

oData WCF service - hide an element

I'm new to WCF. My web project has an ADO.NET Entity Data Model (aka EF edmx), which has the Entity Container Name JobSystemEntities.
I've created a simple oData WCF data service which uses JobSystemEntities, and it works great:
public class JobService : DataService<JobSystemEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("Jobs", EntitySetRights.ReadSingle);
}
However, this exposes all of the properties on the Job. I would like to hide sensitive data, i.e. the Cost field/property/column of the Job table.
I am posting this a but late, but it might help others.
You can use the IgnoreProperties attribute http://msdn.microsoft.com/en-us/library/system.data.services.ignorepropertiesattribute.aspx on your class.
You will have to define a partial Job class in order to do this. Something in the lines of:
namespace DAL.Entities
{
[IgnoreProperties("Cost")]
public partial class Job
{
}
}
I've done something similar to this. A good starting point is found here:
http://weblogs.asp.net/rajbk/archive/2010/05/15/pre-filtering-and-shaping-odata-feeds-using-wcf-data-services-and-the-entity-framework-part-1.aspx
Basically you will need to separate the protected properties of an entity into a separate entity that is linked as a property of the other. Once that is done user a Query Interceptor to restrict when that protected entity can be viewed.
[QueryInterceptor("YourObjectsProtectedProperties")]
public Expression<Func<YourObjectsProtectedProperties, bool>> OnReadYourObjectsProtectedProperties()
{
if (ShowEntityToUser())
return o => true == true;
return o => true == false;
}