How to configure ninject bindings for different scenarios? - asp.net-mvc

When I run my MVC 5 site locally, I want to use these ninject bindings. When I run it in production on azure, I want to use those bindings (which are almost the same, except for a couple different bindings).
How should I detect this, and where should this conditional code go?

To prevent you from having to have separate compilations for each environment, you should drive your DI configuration from web.config. This will keep the door open for a compile once, deploy everywhere strategy.
<appSettings>
<add key="UseSpecialDI" value="true" />
</appSettings>
In your DI config:
bool useSpecialDI = ConfigurationManager.AppSettings["UseSpecialDI"].ToLower() == "true";
if (useSpecialDI)
{
// Use "those settings"
}
else
{
// Use "these settings"
}
Much like your DI configuration, it is best to use fine-grained configuration settings that do specific things rather than broad settings that change large swaths of the DI configuration around.

Related

Can I change the FormsAuthentication cookie name in asp.net dynamically?

I want to set FormsAuthentication cookie name dynammically, for example a guid. how can i do that. I can already change it to whatever I want in web.config. I just can't do it in code and dynamically.Please help.
<authentication mode="Forms">
<forms name="myName" loginUrl="~/Account/Login" defaultUrl="~/Admin/admin" cookieless="UseCookies" slidingExpiration="true" timeout="40320"/>
</authentication>
The reason that I want to do this is, i have several instances of my application on the same host and i do not want them to overwrite each other's cookies.
I have been struggling with Cookies with quite a few days. It has been an awesome learning experience.
So wanted to share the possible ways I found & discovered: There are several HACKs to modify Forms Authentication Cookie name:
You can automate the modification of cookie name under Authenticaiton secion of Web.Config file in Application_Start event in Global.asax. Thanks to Ron for sharing this. But I could not guarantee that the user whose identity would be used to run application domain have enough privileges to modify the file on disk or not. Hence I needed an improvised solution, so I devised following.
Thanks to ILSpy for letting me see inside the FormsAuthentication class, and many thanks to Reflection to let me modify the private field of a class. I used following code to modify the cookie name on run-time with following small piece of code and this worked like a charm !!!
protected void Application_Start(Object sender, EventArgs e)
{
// This will enforce that FormsAuthentication class is loaded from configuration settings for the application.
FormsAuthentication.Initialize();
// The new cookie name whatever you need can go here, I needed some value from my application setting to be prefixed so I used it.
string newCookieName = string.Format("{0}.ASPXAUTH", ConfigurationManager.AppSettings["SomeSettingThatIsUniquetoSite"]);
// Modifying underlying baking field that points to FormsAuthentication.FormsCookieName
Type type = typeof(FormsAuthentication);
System.Reflection.FieldInfo field = type.GetField("_FormsName", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
field.SetValue(null, newCookieName);
}
Suggestions, loopholes are requested as this is my first answer on this forum.
You can't do this in code; the property FormsAuthentication.FormsCookieName is readonly. I would use the following configuration in web.config:
<authentication mode="Forms">
<forms configSource="forms.config" />
</authentication>
Then give each instance of the application its own forms.config:
<forms name="CookieNameForThisInstance" />

How to set SimpleMembershipProvider to require unique email?

I started a new MVC 4 application using VS 2012 and I noticed it is recommending the use of SimpleMembershipProvider.
I like the idea and all the goodies of the WebSecurity class (which helps a lot).
I'd like to be able to set the RequiresUniqueEmail property to true the documentation doesn't have a suggestion on how to accomplish that.
Can you add the property requiresUniqueEmail="true" to the
<membership>
<providers>
<add name="SimpleMembershipProvider"
type="whatever your assembly name is"
...
requiresUniqueEmail="true"/>
tag in your web.config? That's how it's done for the default membership provider. I would imagine it would be the same for the Simple version (unless that feature was not implemented).

ASP.net MVC - using AuthorizeAttribute in multiple environments with Windows Authentication

I'm using windows authentication in my ASP.net MVC 3 application. I have a few different roles in my system:
Administrator
PowerUser
GeneralUser
We have a rule in place that the AD group names are different in each environment.
For example, in Development the role names will be:
Administrator_Dev
PowerUser_Dev
GeneralUser_Dev
In production it would just be:
Administrator
PowerUser
GeneralUser
Is there a good solution for using Authorize in these different environments without changing the code when I need to deploy to a different environment?
Can't you just implement all of the roles? Unless there's a chance of an Administrator_Dev role being the production site...
[Authorize(Roles = "Administrator_Dev, Administrator")]
The only solution I can think of is the conditional compilation.
Define these constants in a file with conditional compile.
#if DEV
public const string AdministratorGroupName = "Administrator_Dev";
#else
public const string AdministratorGroupName = "Administrator";
#endif
This is one of the problems with declarative authorization using custom attributes that needs to be defined at compile-time.
Another alternative is to have another custom attribute and implement the action filter yourself.
I did by simply creating application specific configuration sections in web.config, putting the name of the environment specific AD group in the application configuration section and then use the configuration property on the Authorize Attribute. I can then change the group name by using custom web.config for each environment. For most applications, you need that anyway to be able to have different connection strings for each environment. With this, you can just use the in-built Authorize Attribute.

ASP.NET MVC VirtualPathProvider not working under IIS 6

By ASP.NET MVC plugin architecture, Plug-in architecture for ASP.NET MVC
I have separated DLL(plugin) which contains the views, css and javascript files in the resources. So my own VirtualPathProvider will load the content out from the DLL if that is for the plugin. It works all fine during development. But It appears not working once I deployed it in IIS. (I mapped the whidcard in IIS 6 and the views are showing)
I have registered my VirtualPathProvider in global.asax as
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
HostingEnvironment.RegisterVirtualPathProvider(new MyVirtualPathProvider());
}
For example.
http://localhost/Plugin/MyPlugin.dll/Styles.MyStyles.css
This should be loaded from the plugin.dll but IIS returns 404.
I guess the static files are all handled by the IIS and not went through asp.net and my VirtualPathProvider ? Is there way to get around this? Please shed some light.
Thanks in advance.
If this is IIS 6 you will need a wildcard mapping. See this blog post from Phil Haack.
I've found the workaround by adding the staticFileHandler in the web.config httpHandlers element.
<add verb="GET,HEAD,POST" path="*" type="System.Web.StaticFileHandler" validate="true" />
I've had a number of problems getting an external compiled library containing resources and controllers to work in our MVC environment. It's used across multiple projects and different errors have surfaced in different projects so here's all the things I had to do (so far) to ensure static file handling works:
Include StaticFileHandler in web.config, e.g.:
<add verb="GET,HEAD" path="*.js" name="Static for js" type="System.Web.StaticFileHandler" />
Ensure Static items are ignored in routing:
routes.IgnoreRoute("{*staticfile}", new { staticfile = #".*\
.(css|js|gif|jpg)(/.*)?" });
Register a Virtual Path Provider, e.g.:
System.Web.Hosting.HostingEnvironment.RegisterVirtualPathProvider(new EmbeddedResourceVirtualPathProvider.Vpp(assemblies.ToArray())
{
//you can do a specific assembly registration too. If you provide the assemly source path, it can read
//from the source file so you can change the content while the app is running without needing to rebuild
//{typeof(SomeAssembly.SomeClass).Assembly, #"..\SomeAssembly"}
});
Not required for static files but worth mentioning are what was needed to get the views / controllers working, which was adding MVCContrib and registering the embedded view engine:
PortableAreaRegistration.RegisterEmbeddedViewEngine();

Exclude HttpModule from running for static content on IIS7

I have a problem with my Authentication HttpModule. The problem is that it obviously runs for every single request I get on my web server (IIS7). Because it also uses Session variable, it fails to work properly on CSS, JS files and similar.
I tried to use:
<add name="AuthModuleName" type="..." preCondition="managedHandler" />
but to no avail. It still runs on every request regardless of its extension or mime type. I should also add, there's a setting
<modules runAllManagedModulesForAllRequests="true">
that seemed suspicious to me and actually disabled preConditions on modules. But changing it to false, breaks the application in a completely different way and with a different exception (The SessionStateTempDataProvider requires SessionState to be enabled).
Can anybody help me how to force IIS7 to exclude my HttpModule when requests are made for static content files?
runAllManagedModulesForAllRequests attribute has to be set to false to actually configure any module the way you want. You will have to also correctly reconfigure Session and others as needed, but the main thing is handlers pipeline execution order that handles requests.
The answer was provided in one of my other questions:
Thanks to Peter that provided the answer that worked correctly.
I don't know about an IIS7 setting for that but you can do this.
The session object will be available only for non-static content :
void yourEventHandler(object sender, EventArgs e) {
HttpApplication app = (HttpApplication)sender;
if (app.Context.Session == null) {
return;
}
// then your code here...
}
This will ensure your code won't be run for files like CSS, JS etc. But keep in mind the session object will also not be ready before PostAcquireRequestState event. (For the order of the HttpApplication events, see this page.)
Edit : Also, it appears with ASP.NET Development Server (though I know you said IIS7 in your question), your HttpModule will still run even for static files.

Resources