I have created a new mvc webapp with the following transforms for web.config:
Web.Debug.config
<?xml version="1.0"?>
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="Debug" value="true" xdt:Transform="Insert"/>
</appSettings>
</configuration>
Web.Release.config
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<appSettings>
<add key="Release" value="true" xdt:Transform="Insert"/>
</appSettings>
</configuration>
Then I created a publish profile and called it Release, but I select the Debug(OBS! important) build configuration.
(I know. Stupid example. In my real project they were called Test and Test2.)
When I run the publish action I get the following in the transformed Web.config:
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="Debug" value="true"/>
<add key="Release" value="true"/>
</appSettings>
Both the transformations were performed! Strange! If I change the name of the publish profile to Release2 I get following correct result:
<appSettings>
<add key="webpages:Version" value="3.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="Debug" value="true"/>
</appSettings>
What do you think? Bug?
Met same issue and finally was able to identify the reason and resolve it.
This issue happens because of publish profiles configuration settings mess. When you set up profile with configuration manager you should make sure Current Solution Configuration matches Configuration that is going to be used: Easiest way for configuration to track config Transformations
Otherwise, remember, that before selected Profile configuration, selected Configuration Transformation would be applied.
So, make sure you don't have twice assigned Configuration for different profiles. If so, just add one more configuration for 'failed' profile to resolve it and you get what you expected on transformation applied.
I am using formsauthentication on my MVC project and when testing locally using the Visual Studio Development Server everything works as expected. Once deployed to IIS 7.5 the HTTPContext.User is causing NullReferenceExceptions.
Both Dev and Prod machines are using the same SQL db (at the moment - this will change post-deployment of course) so I know it is not a problem with the DB or data within.
This must be a setting in IIS or my web.config but I cannot find it.
I've tried various changes to my web.config(from suggestions I've found around SE), here is part of my web.config for the current implementation:
<appSettings>
<add key="autoFormsAuthentication" value="true" />
<add key="enableSimpleMembership" value="false" />
<add key="webpages:Version" value="2.0.0.0" />
<add key="webpages:Enabled" value="false" />
<add key="PreserveLoginUrl" value="true" />
<add key="ClientValidationEnabled" value="true" />
****Snip****
<system.web>
<httpRuntime targetFramework="4.5" />
<compilation debug="true" targetFramework="4.5" />
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" cookieless="UseCookies"/>
</authentication>
<pages>
<namespaces>
<add namespace="System.Web.Helpers" />
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization" />
<add namespace="System.Web.Routing" />
<add namespace="System.Web.WebPages" />
<add namespace="ProjectSquid.WebUI.HTMLHelpers" />
</namespaces>
</pages>
<roleManager enabled="true" defaultProvider="CustomRoleProvider">
<providers>
<clear />
<add name="CustomRoleProvider"
type="Project.Domain.Filters.CustomRoleProvider"
connectionStringName="EFDbContext"
enablePasswordRetrieval="false"
cacheRolesInCookie="true"/>
</providers>
</roleManager>
<membership defaultProvider="SimpleMembershipProvider">
<providers>
<clear />
<add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
</providers>
</membership>
<sessionState mode="InProc" customProvider="DefaultSessionProvider">
<providers>
<add name="DefaultSessionProvider" type="System.Web.Providers.DefaultSessionStateProvider, System.Web.Providers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" connectionStringName="EFDbContext" />
</providers>
</sessionState>
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="X-UA-Compatible" value="IE=9" />
</customHeaders>
</httpProtocol>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
<modules runAllManagedModulesForAllRequests="false">
<remove name="FormsAuthentication" />
<remove name="DefaultAuthentication" />
<add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule" preCondition="" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" preCondition="" />
<remove name="UrlRoutingModule-4.0"/>
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" preCondition="" />
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
</system.webServer>
What could cause HttpContext.User to differ from the VS Development Server and the IIS 7.5 implementation?
EDIT:
HttpContext is fed through the inherited BaseController:
protected virtual new CustomPrincipal User
{
get { return HttpContext.User == null? null : HttpContext.User as CustomPrincipal; }
}
public new HttpContextBase HttpContext
{
get
{
return ControllerContext == null ? null : ControllerContext.HttpContext;
}
}
The cookie isn't created until the PostAuthenticationRequest:
public void MvcApplication_PostAuthenticationRequest(object sender, EventArgs e)
{
var authCookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
string encTicket = authCookie.Value;
if (!String.IsNullOrEmpty(encTicket))
{
var ticket = FormsAuthentication.Decrypt(encTicket);
var id = new UserIdentity(ticket);
string[] userRole = Roles.GetRolesForUser(id.Name);
var prin = new CustomPrincipal(id);
HttpContext.Current.User = prin;
Thread.CurrentPrincipal = prin;
}
}
}
The authentication itself appears to be working fine as the function causing the exception starts with [Authorize] and successfully begins executing but fails as null when it reaches the first User reference:
int userT = User.Team.TeamId;
In this context the User being CustomPrincipal BaseController.User.
EDIT2:
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880"
cookieless="UseCookies"
name=".ASPXAUTH"
protection="All"
slidingExpiration="true"/>
</authentication>
EDIT3
Custom IIdentity:
[Serializable]
public class UserIdentity : MarshalByRefObject, IIdentity
{
private readonly FormsAuthenticationTicket _ticket;
public UserIdentity(FormsAuthenticationTicket ticket)
{
_ticket = ticket;
}
public string AuthenticationType
{
get { return "Custom"; }
}
public bool IsAuthenticated
{
get { return !string.IsNullOrEmpty(this.Name); }
}
public string Name
{
get { return _ticket.Name; }
}
public string UserId
{
get { return _ticket.UserData; }
}
public bool IsInRole(string Role)
{
return Roles.IsUserInRole(Role);
}
public IIdentity Identity
{
get { return this; }
}
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (context.State == StreamingContextStates.CrossAppDomain)
{
GenericIdentity gIdent = new GenericIdentity(this.Name, this.AuthenticationType);
info.SetType(gIdent.GetType());
System.Reflection.MemberInfo[] serializableMembers;
object[] serializableValues;
serializableMembers = FormatterServices.GetSerializableMembers(gIdent.GetType());
serializableValues = FormatterServices.GetObjectData(gIdent, serializableMembers);
for (int i = 0; i < serializableMembers.Length; i++)
{
info.AddValue(serializableMembers[i].Name, serializableValues[i]);
}
}
else
{
throw new InvalidOperationException("Serialization not supported");
}
}
Custom IPrincipal:
interface ICustomPrincipal : IPrincipal
{
int Id { get; set; }
string Name { get; set; }
string Role { get; set; }
}
public class CustomPrincipal : IPrincipal
{
public CustomPrincipal(UserIdentity identity)
{
this.Identity = identity;
}
public IIdentity Identity { get; private set; }
Most likely, you are attempting to retrieve HttpContext.User before it has been initialized. This behavior differs between IIS Classic (or the Visual Studio Web Server) and IIS Integrated pipeline modes, which would explain why you are seeing different behavior between the environments.
Explanation
HttpContext is part of an application's runtime state. In modern hosting environments (IIS integrated pipeline mode and OWIN), HttpContext is not populated until after the Application_Start method is complete. Any behavior that you have that requires HttpContext.User should not be executed until the Application_BeginRequest event or after.
Reference: Request is not available in this context
It's not clear from your post since configuring the authentication depends on various settings in your project plus the configuration file. For example in Web.config file, there are several places to customize/configure the authentication like this one (the most important rule) that you haven't placed in your post:
<system.web>
<authentication mode="" />
</system.web>
As you know, since the configuration system is based on a hierarchical system of management system that uses **.config* files, you should consider the defaults, perhaps by <remove/> or <add/> some parameters. The configuration files for IIS 7 and later are located in your %WinDir%\System32\Inetsrv\Config folder, and the primary configuration files are:
ApplicationHost.config - This configuration file stores the settings for all your Web sites and applications.
Administration.config - This configuration file stores the settings for IIS management. These settings include the list of
management modules that are installed for the IIS Manager tool, as
well as configuration settings for management modules.
Redirection.config - IIS 7 and later support the management of several IIS servers from a single, centralized configuration file.
This configuration file contains the settings that indicate the
location where the centralized configuration files are stored.
Note: Some settings can be delegated to Web.config files, which may override settings in the ApplicationHost.config file. In addition, settings that are not delegated cannot be added to Web.config files.
Tip: A default installation of IIS 7 does not contain Digest authentication, so adding the settings for Digest authentication to your ApplicationHost.config will have no effect or may cause errors until the Digest authentication module is installed.
You need to see both local and deployment configurations to meet your purpose. If you have trouble with integrated pipeline, see the following pages to take its advantages :
Debugging the IIS7 integrated pipeline with failed request
tracing
How to Take Advantage of the IIS 7.0 Integrated Pipeline
Update About SlidingExpiration : According to MSDN:
Sliding expiration resets the expiration time for a valid
authentication cookie if a request is made and more than half of the
timeout interval has elapsed.
If the cookie expires, the user must re-authenticate. Setting the SlidingExpiration property to false can improve the security of an application by limiting the time for which an authentication cookie is valid, based on the configured timeout value. So I think there's no need to use this as false. This means It will expire cache after time period at the time of activating cache if any request is not made during this time period. This type of expiration is useful when there are so many data to cache. So It will put those items in the cache which are frequently used in the application. So it will not going to use unnecessary memory.
I'm trying to authenticate users through LDAP in C#. Each time I try to log in, I get the 'Input string was not in a correct format' error.
This is my connection string:
<connectionStrings>
<add name="MyConnectionString" connectionString="LDAP://123.193.111.22:389.local" />
</connectionStrings>
<system.web>
<roleManager enabled="true" />
<membership defaultProvider="MyMembershipProvider"><providers>
<add name="MyMembershipProvider"
connectionStringName="MyConnectionString"
type="System.Web.Security.ActiveDirectoryMembershipProvider,
System.Web, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
connectionUsername="MyUsername"
connectionPassword="MyPassword"
connectionProtection="Secure"
enableSearchMethods="true" />
</providers>
</membership>
<trust level="Full" />
</system.web>
<authentication mode="Forms">
<forms name=".ADAuthCookie" loginUrl="~/Admin/Login"
timeout="450" slidingExpiration="false" protection="All"/>
</authentication>
The error seems to be at type="System.Web.Security.ActiveDirectoryMembershipProvider. Any suggestions would be greatly appreciated. Thanks!
I've managed to figure it out. Had to rework the membership provider code and now I'm able to authenticate users.
I'm all of a sudden getting the following error with my Web.config file and I don't understand what it means:
Parser Error Message: The attribute 'connectionStringName' is missing or empty.
Line 24: <providers>
Line 25: <clear />
Line 26: <add name="SMDPortalMembershipProvider" type="SMDPortalMembershipProvider" />
Line 27: </providers>
Line 28: </membership>
Source File: c:\inetpub\wwwroot\web.config Line: 26
Version Information: Microsoft .NET Framework Version:4.0.30319;
ASP.NET Version:4.0.30319.272
Here's my config file:
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<connectionStrings>
<add name="ApplicationServices"
connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnetdb.mdf;User Instance=true"
providerName="System.Data.SqlClient"/>
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0">
<assemblies>
<add assembly="UODOTNET, Version=2.2.5.7444,
Culture=neutral, PublicKeyToken=335F3FBD4BE82339"/>
<add assembly="System.Core, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=B77A5C561934E089"/>
</assemblies>
</compilation>
<authentication mode="Forms">
<forms loginUrl="Default.aspx" timeout="2880" />
</authentication>
<authorization>
<deny users="?" />
</authorization>
<membership defaultProvider="SMDPortalMembershipProvider">
<providers>
<clear />
<add name="SMDPortalMembershipProvider" type="SMDPortalMembershipProvider" />
</providers>
</membership>
<customErrors mode="Off"/>
<sessionState cookieName="smd_portal_session" timeout="100"/>
</system.web>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
There is no error when I load the Default.aspx page, but as soon as my code calls upon the Membership class I'm getting the error.
Your membership provider's config section needs a connectionStringName attribute. Without that connectionStringName, it doesn't know what database to look for membership information in.
You need to add the name of one of your the connection strings in the connectionStrings section to the add tag on line 26.
The connectionStringName attribute is required in order for your Web.Config to be valid. You can't use the Membership class without it.
This is in IIS express.
public class FooHandler : HttpTaskAsyncHandler
{
public override async Task ProcessRequestAsync(HttpContext context)
{
var val = await new FooRequest().ProcessRequest();
context.Response.Write(val);
}
}
That s the handler and below is web.config.
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<sessionState mode="Off" />
<compilation debug="true" targetFramework="4.5" />
<machineKey compatibilityMode="Framework45" />
<httpHandlers>
<add verb="*" path="*.foo" validate="false" type="FooServer.FooHandler" />
</httpHandlers>
</system.web>
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add name="FooHandler" verb="*" path="*.foo" type="FooServer.FooHandler" />
</handlers>
</system.webServer>
</configuration>
I keep getting the below error. google didnt help. may be you can?
HTTP Error 404.7 - Not Found
The request filtering module is configured to deny the file extension.
Most likely causes:
Request filtering is configured for the Web server and the file extension for this request is explicitly denied.