Adding parameter to AuthorizeAttribute constructor causes failure in MvcSiteMapProvider? - asp.net-mvc

I've been using MvcSiteMapProvider based on authorize attributes and it was all right until we introduced a new class derived from AuthorizeAttribute. Main difference is in its constructor signature:
public MyAuthorizeAttribute(param RoleCode[] roles) {
Roles = string.join(",", roles.Select(r => r.ToString());
}
And... MvcSiteMapProvider shown unexpected result: only actions marked by MyAuthorizeAttribute became invisible. I've checked that by disabling this constructor - everything went as it had been before adding a parameter to the constructor. Also - it's not params specific - any parameter (event int) leads to such behaviour.
AS I understood from MvcSiteMapProvider sources, it emits some code to emulate authorize attributes - but looks like it's impossible to save assembly generated by external code. I know that there is a workaround - use some kind of enumerable property, but have you got any suggestions how to make it work with constructor parameters? Do you know why MvcSiteMapProvider behaves like that?

So, after spending some time in debugging, I realized the answer: dynamic proxies.
The problem is that during request execution inside MVC framework there is no easy way to find out how a class derived from AuthorizeAttribute performs its work. In case of access check failure some could throw exception, some - return 401 status code, some redirect to login page at once, and so on.
But MvcSiteMapProvides does that! It uses the following workaround:
if class is AuthorizeAttribute:
create an instance of InternalAuthorize class which is fairly simple.
copy all properties there and
invoke AuthorizeCore method which returns boolean value.
else
generate a proxy class derived from a type of attribute,
create instance, /// << here we get an exception
copy all properties there and
invoke AuthorizeCore method which returns boolean value.
As it is clear, that's not an easy task to make a proxy, which is aware of your constructor parameters. Exception about default constructor absence is thrown, of course, but it is then consumed by empty catch clause. That is really sad - at least a single debug trace would have saved me a couple of hours.
So the answer at last:
Obviously you should use parameterless attribute constructor (why oh why that's not mentioned anywhere?)
Make custom acl provider: implement IAclModule interface and unleash your knowledge about your own authorize attributes within it.

Related

Calling a static method from Thymeleaf TEXT template - how to bypass the Restricted mode

Is it possible to call a static method from a Thymeleaf textual template?
Official guide mentions that it should be possible to call a method like this:
<p th:text="${#myapp.translator.Translator#translateToFrench(textVar)}">Some text here...</p>
When I try to use it in my textual template (TemplateResolver's mode is set to TemplateMode.TEXT), I get a this exception:
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating OGNL expression: "#java.lang.System#currentTimeMillis()" (template: "template.txt" - line 1, col 18)
Here is my sample template:
System millis: [(${#java.lang.System#currentTimeMillis()})]
After googling for a while, I also found this form of calling methods:
System millis: [(${T(java.lang.System).currentTimeMillis()})]
which fails with the same error.
What I need to do is somehow allow usage of a custom number formatter class from a template (functionality of the #numbers utility object is not rich enough for my case).
I can call methods on a non-static class by providing it as a context variable like this:
Some value: [(${formatter.format(someValue)})]
but it would be easier for me to use a static class without a need to explicitly adding it to each template's context.
BTW, I do not use Spring, just pure Thymeleaf.
Update
I should've spend more time to analyze the stack trace of the Thymeleaf exception I got.
It turns out, that the root cause of this behavior was the org.thymeleaf.exceptions.TemplateProcessingException: Instantiation of new objects and access to static classes is forbidden in this context exception, which is results from this change: https://github.com/thymeleaf/thymeleaf/issues/809
Downgrading to Thymeleaf 3.0.11 "fixes" it.
Now I'm looking for a solution to bypass this new Resctricted mode on the latest Thymeleaf (3.0.12 for the moment). I'm sure it's safe in my case, because I'm the only author of both code and templates.
An alternative would be to use the th:with attribute. It's a little more verbose, but still should allow you the same flexibility. (This works for me on 3.0.12.RELEASE.)
[# th:with="time=${#java.lang.System#currentTimeMillis()}"]System millis: [[${time}]][/]
https://github.com/thymeleaf/thymeleaf/issues/816#issuecomment-826401631 has extensive info on why this was done and possible workarounds. In your case, it will be best to add a model attribute in your controller and use that instead of calling the static method in the template.
#Controller
public class MyController {
public String myControllerMethod(Model model) {
model.addAttribute("time", System.currentTimeMillis());
return "name-of-the-thymeleaf-template";
}
}
and update your template to use:
System millis: [(${time})]

What things can I put inside a BaseController to make my MVC life simpler

My base controller has:
[Authorize(Roles = "sys_admin")]
I want to have one action in a controller that's different and is available to "user" and "sys_admin". Can I override and how do I do that?
Also any suggestions on what else I could put in a base controller that might make my coding simpler. For example what's in your base controllers?
Anything that you use in every controller - attributes, methods, properties, etc. The same stuff you would put in any base class.
Just to add to the discussion, I have a few extra utility methods in my shared controller. I write a bunch of little apps for corporate use, so I try to repeat code as little as possible here.
getContext(): Puts together an object containing user info like IP, hostname, id, etc. for logging purposes.
Shared Views/Partials such as Error, Default, and Redirect (used for redirecting ajax requests).
RedirectToError(): I created this to use similar to RedirectToAction. I load up an ErrorObject with info, throw it in session, and return a Redirect to my Error page.
General logging and tracing methods so I can quickly spit out information to a file.
I override OnActionExecuting and check if my session is still valid and redirect to login if its not. Probably better with attributes...went with quick and dirty. Also trace Url.PathAndQuery for debugging here.
Any data access actions that I would use across views with ajax, like loading up a list of departments.
OnException is overridden, as well.
That's what I got in mine so far.
In my base controllers I actually put some utility method ([NonAction]) collected over time. I prefer to add functionalities to Controllers by decorating with Attributes if possible.
Lately my base controller has:
some Properties for retrieving information about the current user (my app
specific informations, not the User.Identity stuffs)
A simple protected override void OnException(ExceptionContext
filterContext); override for at least logging unhandled exception and have
some sort of automatic notifications
A bunch of Cookies related methods (WebForms auth cookies management
for example)
A bunch of usefull standard attributes (usually [Authorize], [HandleError], [OutputCache]) in its declaration.
some standard method for preparing widely used json data types on the fly (when possible I prefer to have a standard json object with ErrorCode, ErrorMessage and a UserData).
With time you'll find more and more utilities to keep with your controllers, try to keep an assembly with the simpler ones (avoiding heavy dependencies), will come handy with your next MVC projects. (the same goes for Helpers and to some degree also for EditorTemplates).
For the Authorize Attribute part, well, I think the cleanest way is to write your own AuthorizeAttribute class, specifically a NonAuthorizeAttribute. I think I've also seen it somewhere on SO.
You can also play with the Order Property of the default AuthorizeAttribute - put different Order in BaseController and in Action, in order to have Action's one executed first, but I cannot recall if you can actually break the Attributes processing chain.
Regards,
M.
We cant tell you what you need in your base controller, you have to reveal these kind of thing as you implement your controllers and see repeating code.. Dont hesitate to refactor these things to your BaseController, and keep in mind, that maybe you should have 2 or more BaseControllers, or 2-layer hierarchy of BaseControllers.
I give you two tips, what i always have in my BaseController :
super-useful helper method for interface-based model binding :
protected T Bind<T, U>()
where T : U, new()
where U : class
{
T model = new T();
TryUpdateModel<U>(model);
return model;
}
You can then have multiple "sets" of properties you want to bind in different scenarios implemented as interfaces, and simple model bind your object (even existing object, from DB) with incoming values.
2.If you use custom AcionResults (maybe your specific Json builders etc.), make your "shortcuts" methods in BaseController. Same thing as View() method is shortcut for return new ViewResult(...)
To add more to the good responses already here -
caching caching caching caching
See
Disable browser cache for entire ASP.NET website

Why are Controller Constructors fired before the Initialize method

I have a base Controller ApplicationController that needs to grab the URL Host and do some processing before the child controllers are fired. Since controller constructors are fired before RequestContext is initialized I have to override Initialize method to do my processing.
ApplicationController:
Protected Overrides Sub Initialize(ByVal requestContext As System.Web.Routing.RequestContext)
MyBase.Initialize(requestContext)
Dim host as String
host = Request.Url.Host.ToString
End Sub
What is the logic behind having Controller Constructors fire before the Initialize method?
Also what are the rules to what should be placed in the Initialize Method.
Assuming that constructors are the first instance method ever to be fired in a .NET class, that shouldn't come as a surprise and is not really something MVC specific. It's more how the .NET framework works.
The MVC framework needs to first instantiate a controller and then initialize it => it calls the constructor first. And because performing lots of code that could potentially might throw exceptions, etc... is not always best to be put in a constructor => the presence of the Initialize method. As far as this method is concerned I must admit that I have written lots of ASP.NET MVC code and never had to use it. Action filters always seemed like a better alternative.
So to answer your question:
Also what are the rules to what should be placed in the Initialize Method.
I've never ever put any code and never ever need to override this method. I've always preferred using action filters because this way I am no longer in the obligation of deriving from a common base controller (not that this is a problem).
Sometimes, maybe you would want your request to initialize your variables, so in this case you should use the Initialize method.
For example, if you want to initialize some variables in a different way when the request is local or not, etc.

Using IoC to provide a custom ModelMetadataProvider in MVC3

I'm currently overriding the default ModelMetadataProvider in the Global.asax file using this
ModelMetadataProviders.Current = new RedSandMetadataProvider(ModelMetadataProviders.Current);
and this works perfectly. But I'd like to use the IDependancyResolver feature of MVC3 to let IoC provide the ModelMetadataProvider implementation instead. I'm using StructureMap to do it (Just installed it into the project using NuGet) but for some reason it not behaving as expected.
x.For<ModelMetadataProvider>().Use(new RedSandMetadataProvider(ModelMetadataProviders.Current));
I put a breakpoint on the constructor of RedSandMetadataProvider() and it is getting hit. And I also put a breakpoint on the GetServices() function of the automatically added SmDependencyResolver.cs file to make sure it was IoC that was calling my constructor, and everything seems fine, the constructor gets called on the second page load I think, but it never calls my GetMetadataForProperty() function of my MetadataProvider. Now I KNOW this gets called correcetly when I set it up in the Global.asax, but every time I try to achieve the same result using IoC, I see the constructor called on my class and that's it. I tried adding a .Singleton() to the StrctureMap registration of the type and that causes my constructor to get called much sooner but it still never actually USES the object after it's constructed.
Am I missing something?
You need to implement IMvcServiceLocator and call MvcServiceLocator.SetCurrent() to tell MVC to use StructureMap: http://bradwilson.typepad.com/blog/2010/07/service-location-pt2-controllers.html
I solved my problem with this issue in another question.
Setting up DependancyResolver in MVC3 using StructureMap for ModelMetadataProvider & ModelValidatorProvider
Please see it if you're encountering problems with this as well.

ASP.NET MVC and IoC - Chaining Injection

Please be gentle, I'm a newb to this IoC/MVC thing but I am trying. I understand the value of DI for testing purposes and how IoC resolves dependencies at run-time and have been through several examples that make sense for your standard CRUD operations...
I'm starting a new project and cannot come up with a clean way to accomplish user permissions. My website is mostly secured with any pages with functionality (except signup, FAQ, about us, etc) behind a login. I have a custom identity that has several extra properties which control access to data... So....
Using Ninject, I've bound a concrete type* to a method (Bind<MyIdentity>().ToMethod(c => MyIdentity.GetIdentity()); so that when I add MyIdentity to a constructor, it is injected based on the results of the method call.
That all works well. Is it appropriate to (from the GetIdentity() method) directly query the request cookies object (via FormsAuthentication)? In testing the controllers, I can pass in an identity, but the GetIdentity() method will be essentially untestable...
Also, in the GetIdentity() method, I will query the database. Should I manually create a concrete instance of a repository?
Or is there a better way all together?
I think you are reasonably on the right track, since you abstracted away database communication and ASP.NET dependencies from your unit tests. Don't worry that you can't test everything in your tests. There will always be lines of code in your application that are untestable. The GetIdentity is a good example. Somewhere in your application you need to communicate with framework specific API and this code can not be covered by your unit tests.
There might still be room for improvement though. While an untested GetIdentity isn't a problem, the fact that it is actually callable by the application. It just hangs there, waiting for someone to accidentally call it. So why not abstract the creation of identities. For instance, create an abstract factory that knows how to get the right identity for the current context. You can inject this factory, instead of injecting the identity itself. This allows you to have an implementation defined near the application's composition root and outside reach of the rest of the application. Besides that, the code communicates more clearly what is happening. Nobody has to ask "which identity do I actually get?", because it will be clear by the method on the factory they call.
Here's an example:
public interface IIdentityProvider
{
// Bit verbose, but veeeery clear,
// but pick another name if you like,
MyIdentity GetIdentityForCurrentUser();
}
In your composition root you can have an implementation of this:
private sealed class AspNetIdentityProvider : IIdentityProvider
{
public MyIdentity GetIdentityForCurrentUser()
{
// here the code of the MyIdentity.GetIdentity() method.
}
}
As a trick I sometimes have my test objects implement both the factory and product, just for convenience during unit tesing. For instance:
private sealed class FakeMyIdentity
: FakeMyIdentity, IIdentityProvider
{
public MyIdentity GetIdentityForCurrentUser()
{
// just returning itself.
return this;
}
}
This way you can just inject a FakeMyIdentity in a constructor that expects an IIdentityProvider. I found out that this doesn’t sacrifice readability of the tests (which is important).
Of course you want to have as little code as possible in the AspNetIdentityProvider, because you can't test it (automatically). Also make sure that your MyIdentity class doesn't have any dependency on any framework specific parts. If so you need to abstract that as well.
I hope this makes sense.
There are two things I'd kinda do differently here...
I'd use a custom IPrincipal object with all the properties required for your authentication needs. Then I'd use that in conjunction with custom cookie creation and the AuthenticateRequest event to avoid database calls on every request.
If my IPrincipal / Identity was required inside another class, I'd pass it as a method parameter rather than have it as a dependency on the class it's self.
When going down this route I use custom model binders so they are then parameters to my actions rather than magically appearing inside my action methods.
NOTE: This is just the way I've been doing things, so take with a grain of salt.
Sorry, this probably throws up more questions than answers. Feel free to ask more questions about my approach.

Resources