asp.net mvc: disabled RoleManager is still executed - asp.net-mvc

I have a web site where configured with:
<roleManager enabled='false'></roleManager>
But I still can see roleManager being executed in the pipeline (by looking at traces, also I am getting exception when roleManager tries to load roles from SQL providers configured in machine.config)
How can I disable roleManager?

fix
add enableSimpleMembership with value false app setting to your web.config.
cause
<roleManager enabled="false" />
will cause Roles.Enabled flag to be set to false, as expected,
but there is WebMatrix.WebData.WebSecurity that says:
internal static void PreAppStartInit()
{
if (!ConfigUtil.SimpleMembershipEnabled)
return;
...
Roles.Enabled = true;
...
}
this will override roleManager setting (this code is executed before RoleManager module is).
to disable SimpleMembership you can add app setting enableSimpleMembership with value="false" (web.config):
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="enableSimpleMembership" value="false" />
</appSettings>
</configuration>
this will prevent webmatrix from enabling RoleManager.
Another solution (hack) is to remove RoleManager module from the list of modules:
....
<system.webServer>
<modules>
<remove name="RoleManager"/>
</modules>
....

no... I don't think it's correct, even with enableSimpleMembership=false, you'd still need to implement a Dummy RoleProvider, otherwise, exception "The Role Manager feature has not been enabled."
Here's how to implement a dummy RoleProvider:
Turning off only the Role Provider in SimpleMembership

Related

Get Mail Setting from Web.Config in SendAsync Method?

I am working on Forgot Password Functionality. In my web.config file I have done the mail settings:
<system.net>
<mailSettings>
<smtp from="email">
<network host="host" port="25" userName="" password="=" enableSsl="true" />
</smtp>
</mailSettings>
</system.net>
In my SendAsync method I am trying to read setting from web.config:
SmtpClient client = new SmtpClient();
return client.SendMailAsync(ConfigurationManager.AppSettings["SupportEmailAddr"],
message.Destination,
message.Subject,
message.Body);
I have no idea what is this: AppSettings["SupportEmailAddr"]
I took this from here.
It is giving me following exception:
Value cannot be null. Parameter name: from
In your web.config file you have a section called: <appSettings>.
That is what ConfigurationManager.AppSettings is referring too.
["SupportEmailAddr"] is looking at a specific setting called SupportEmailAddr.
In your web.config it would look something like this:
<appSettings>
<add key="SupportEmailAddr" value="someone#example.com" />
</appSettings>
You are getting the value cannot be null message because you will not have the setting in your web.config as above.
So to fix the error message find your <appSettings> and add:
<add key="SupportEmailAddr" value="someone#example.com" />
Alternatively, if you have the current value in your AppSettings already then just change the key that you are looking for in the C# code.
ConfigurationManager.AppSettings["CorrectAppSettingKey"]
Note: if you plan on using any of the web.config inheritance features you should WebConfiguratonManger.AppSettings instead of ConfigurationManager.AppSettings. See the difference between the two here: What's the difference between the WebConfigurationManager and the ConfigurationManager?

How to override Elmah applicationname set in Web.config

We have a multi-tenanted MVC app, meaning that exactly the same app is published to multiple IIS virtual directories / applications, and then the app its self works out who it is, and skins its self (css) accordingly.
This is all very well, but anything logged by ELMAH in our elmah database gets logged under the same applicationName, as this is pulled out of Web.Config elmah section below where everything would be logged as "MyappName" :
<configuration>
[...]
<elmah>
<security allowRemoteAccess="false" />
<errorLog
type="Elmah.SqlErrorLog, Elmah"
connectionStringName="elmah"
applicationName="MyappName" />
</elmah>
</configuration>
The question is therefore how to override the applicationName setting from web.config with something specific so we can distinguish errors for a given tenant web site.
As this is configurable within the web.config, ELMAH are already providing you with a way to specify the application name when the application is deployed to different locations - it's just a case of making use of it.
This would generally be something that you would manipulate as part of your deployment steps. If you are doing it manually then it's going to be a pain, but it could be easily manipulated by using a web.config transform.
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<elmah>
<errorLog applicationName="MyappName" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
</elmah>
</configuration>
I wonder if the following might work, if you put the following into your Global.asax:
var service = ServiceCenter.Current;
ServiceCenter.Current = context =>
{
var connectionString = "YOUR CONNECTION STRING";
var container = new ServiceContainer(service(context));
var log = new SqlErrorLog(connectionString) { ApplicationName = "APP NAME HERE" };
container.AddService(typeof(ErrorLog), log);
return container;
};

Miniprofiler and umbraco

I'm running an instance of umbraco 7. But I can't seem to set miniprofiler to work with it.
Set this on my global.asax:
protected void Application_BeginRequest()
{
if (Request.IsLocal)
{
MiniProfiler.Start();
}
}
protected void Application_EndRequest()
{
MiniProfiler.Stop();
}
Also defined the handler on the web.config:
<add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />
Any help is truly appreciated.
MiniProfiler is built in to Umbraco v6 and v7. You don't have to manually setup it. All you have to do is to enable debug mode by setting key in AppSettings:
<add key="umbracoDebugMode" value="true" />
And load page with ?umbDebug=true query string parameter.
Does your global.asax file inherit from the umbraco global http class, or the one where you are writing this code? If the former, it won't work. Try using Web Activator instead. Or inherit from the umbraco global file in your global.asax.cs.

Problems with IIS and Custom Membership Provider + Custom Role Provider

I have developed my own classes for Custom Membership and Role providers.
Everything works locally. Nonetheless, after deploying the solution to IIS for testing, my login action seems to work (at least, the action validates the username+password and the user appears to be authenticated) but whenever I try to access actions that are decorated with annotations like
[Authorize(Roles="Employee, Admin")]
I keep getting redirected to the login page, as if the user didn't have the necessary role (he does, though).
So locally, the application succeeds in validating users and checking the authenticated user's roles before executing actions (thus, I assume that my methods on both classes are correct) but on IIS it looks like the role provider isn't working properly. Anyone happens to know where might I be wrong or how can I get a better view on my problem?
In my Web.Config:
<system.web>
(...)
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" />
</authentication>
<membership defaultProvider="CustomMembershipProvider">
<providers>
<clear />
<add name="CustomMembershipProvider" type="MyApplication.Infrastructure.CustomMembershipProvider" connectionStringName="DBEntities" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="6" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10" applicationName="/" />
</providers>
</membership>
<roleManager enabled="true" defaultProvider="CustomRoleProvider">
<providers>
<clear />
<add name="CustomRoleProvider" type="MyApplication.Infrastructure.CustomRoleProvider" connectionStringName="DBEntities" applicationName="/" />
</providers>
</roleManager>
(...)
</system.web>
Thanks in advance.
EDIT: Aditional Info.
I just modified one of my actions' anotation to simply [Authorize] and it works. So, I believe that the authentication works and the problem must be related to the Role provider.
I'm using Entity Framework for my Data Model, the con. string is as follows:
I managed to register a user and log in using the that newly created account, which would mean that the DB connection and the Custom Membership Provider(?) are working properly.
A "#foreach (String str in Roles.GetRolesForUser(User.Identity.Name)){#str} prints the roles locally and doesn't print anything when deployed.
Ok, I fixed it. Here's the explanation in case someone needs it in the future:
After narrowing out the causes (as seen in my edits), I figured out that the problem must be related to my CustomRoleProvider.
That class has methods like this one:
public override string[] GetRolesForUser(string Username)
{
List<string> roles = new List<string>();
using (DBEntities _db = new DBEntities())
{
try
{
var dbRoles = from r in _db.UserRole
where r.Users.Username == Username
select r;
foreach (var role in dbRoles)
{
roles.Add(role.Role.Name);
}
}
catch
{
}
}
return roles.ToArray();
}
So I was catching an exception and not doing anything with it. I removed the try-catch block, and got this message:
There is already an open DataReader associated with this Command which must be closed first.
A bit of stackoverflowing and I found this: There is already an open DataReader associated with this Command which must be closed first
Turns out my local connection string had MultipleActiveResultSets=true but the connection string on my publish settings didn't. I modified my publish settings and voilĂ , seems to be working now.
I don't really know the advantages/disadvantages of having that setting, but it is working and I really need to move on. Thank you all for your help anyway.
I have had the similar issue. After adding machineKey to web.config everything works all right.
<system.web>
<machineKey validationKey="2E417D4AC04F20FA6CE1CF1EFE23FBF1695BF6981B605B1B8628D2182C43D0B10E48C4A83FDCE0D1D6300095D9EE1B8746A37E2C3256554405983DCAA7622875" decryptionKey="FA6D35C22BF7E5E9E4438052B924CCC017521137C5EB017D07C7038B80C5F726" validation="SHA1" decryption="AES" />
</system.web>

NHibernate + Spring.NET lazy loading failed - no session

I use Spring.NET AOP for transaction and session management with NHibernate. When user makes several requests too quick - lazy loading is failed with exception "no session or session was closed".
I use SpringSessionContext as CurrentSessionContext in NHibernate configuration
public class FluentSessionFactory : LocalSessionFactoryObject
{
protected override ISessionFactory NewSessionFactory(Configuration config)
{
var conf = Fluently
.Configure()
.Database(
MsSqlConfiguration
.MsSql2008
.ConnectionString(c => c.FromConnectionStringWithKey("MyConnection"))
// TODO: use ExposeConfiguration method
.CurrentSessionContext<SpringSessionContext>()
)
.Mappings(
m => m.FluentMappings
.AddFromAssembly(this.GetType().Assembly)
)
.BuildSessionFactory();
return conf;
}
}
In xml config:
<object id="SessionFactory" type="IndustryTracker.NHibernateRepository.FluentSessionFactory, IndustryTracker.NHibernateRepository">
<property name="DbProvider" ref="DbProvider" />
</object>
and OpenSessionInView module
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate31"/>
</modules>
</system.webServer>
Application implements next workflow for getting entities from db: View -> Controller -> Manager -> Repository and same to other side. So session is created per request, transaction - per call to manager.
<object id="TransactionManager" type="Spring.Data.NHibernate.HibernateTransactionManager, Spring.Data.NHibernate31">
<property name="DbProvider" ref="DbProvider"/>
<property name="SessionFactory" ref="SessionFactory"/>
</object>
<tx:advice id="TxAdvice" transaction-manager="TransactionManager">
<tx:attributes>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<object id="Pointcut" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
<property name="patterns">
<list>
<value>MyAppication.Managers.AccountManager</value>
<value>MyAppication.Managers.CompanyManager</value>
</list>
</property>
</object>
<aop:config>
<aop:advisor advice-ref="TxAdvice" pointcut-ref="Pointcut"/>
</aop:config>
What are possible reasons of such behaviour and how can I solve this problem(Not.LazyLoad() and NHibernateUtil.Initialize() are not acceptable variants in my context)?
After some search I found that problem was in configuration. There was spring WebSupportModule missing http module in config, so the correct one is:
<httpModules>
<add name="Spring" type="Spring.Context.Support.WebSupportModule, Spring.Web"/>
<add name="OpenSessionInView" type="Spring.Data.NHibernate.Support.OpenSessionInViewModule, Spring.Data.NHibernate31"/>
</httpModules>
So Marijn was right - it was weak wiring to spring.
1. Session factory configured for OpenSessionInViewModule?
You might have forgotten to configure the session factory for the OpenSessionInViewModule:
<appSettings>
<add key="Spring.Data.NHibernate.Support.OpenSessionInViewModule.SessionFactoryObjectName"
value="SessionFactory"/>
</appSettings>
This has to be done in the app settings.
2. Correct FluentNHibernate based spring session factory?
You seem to be configuring your session factory in code. Have you tried configuring the session factory like described in the docs and on BennyM 's blog? Your NewSessionFactory method returns a session factory from straight from Fluent NHibernate, bypassing all spring.net support.
3. Is your session factory transaction aware?
<object id="SessionFactory"
type="IndustryTracker.NHibernateRepository.FluentSessionFactory, IndustryTracker.NHibernateRepository">
<property name="DbProvider" ref="DbProvider" />
<!-- provides integation with Spring's declarative transaction management features -->
<property name="ExposeTransactionAwareSessionFactory" value="true" />
</object>
4. Does your controller have dependencies with scope="application" or no scope definition?
I might have been looking in the wrong direction here. If your controller has dependencies of application scope, it would mean that quick requests could interfere. The default is "scope="application"; so you'd want to check collaborators without scope definitions too. See the docs on web scopes.

Resources