we login and set object Csla.ApplicationContext.User succesfull after:
public static void Login(string userName, string password, EventHandler callback)
{
var dp = new DataPortal<AppIdentity>();
dp.FetchCompleted += (o, e) =>
{
if (e.Error == null)
{
var principal = new AppPrincipal(e.Object);
if (principal.Identity.IsAuthenticated)
Csla.ApplicationContext.User = principal;
else
Csla.ApplicationContext.User =
new Csla.Security.UnauthenticatedPrincipal();
}
else
{
Csla.ApplicationContext.User =
new Csla.Security.UnauthenticatedPrincipal();
}
callback(null, EventArgs.Empty);
};
dp.BeginFetch(new Csla.Security.UsernameCriteria(userName, password ));
}
later in system after a few transactions when we do this call:
return ((Business.AppIdentity)Csla.ApplicationContext.User.Identity).ImpersonatedUserID; //throws error
the object Csla.ApplicationContext.User.Identity and values got lost and turn from
AppIdentity : CslaIdentityBase<AppIdentity> to System.Security.Principal.GenericIdentity.
Why?
just change web.config:
from:
<appSettings>
<add key="CslaAuthentication" value="Windows"/>
</appSettings>
to:
<appSettings>
<add key="CslaAuthentication" value="Custom"/>
</appSettings>
I have exactly the same problem, but this change did not help. Can you post your AppIdentity class?
My AppIdentity class looks like:
[Serializable]
public partial class AppIdentity : Csla.Security.CslaIdentity
{
public User UserObject { get; set; }
public AppIdentity()
{ }
}
public partial class AppIdentity
{
private void DataPortal_Fetch(Csla.Security.UsernameCriteria credentials)
{
this.AuthenticationType = "Custom";
this.Roles = new Csla.Core.MobileList<string>();
User user = User.GetByUsernamePassword(credentials.Username, credentials.Password);
if(user != null && user.Username.Equals(credentials.Username) && user.Password.Equals(credentials.Password))
{
this.UserObject = user;
this.Name = (String.Format("{0} {1}", user.Firstname, user.Lastname)).ToUpper();
this.IsAuthenticated = true;
}
else
{
this.UserObject = null;
this.Name = "";
this.IsAuthenticated = false;
}
}
}
The CslaAuthentication setting value on the client and server must match. One common mistake is to set the value only on the server.
But I set the CslaAuthentication also on the client side in the web.config and it doesn't work.
<appSettings>
<add key="CslaAuthentication" value="Custom"/>
</appSettings>
What kind of client? Windows or Silverlight?
Silverlight Client... with CSLA 4.1
It is important to understand that only serializable objects and properties will flow from client to server.
In Silverlight the term "serializable" has special meaning (discussed at some length in the Using CSLA 4: Creating Business Objects ebook) that includes:
Your code snippet appears to use a property without a managed backing field, and you don't appear to be doing manual serialization. That's probably the issue. I strongly recommend using managed properties for all Silverlight classes, including custom principal/identity types.
only my server have that entry, the client has none:
appIdentity:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Csla;
using Csla.Serialization;
using Csla.Security;
namespace Business
{
//[Serializable]
//public partial class AppIdentity : Csla.Security.CslaIdentity
[Serializable]
public partial class AppIdentity : CslaIdentityBase<AppIdentity>
{
#if SILVERLIGHT
public AppIdentity()
{ }
#else
private AppIdentity()
{ }
#endif
//must base not be updated?
#region Business Methods
public static PropertyInfo<int> IdProperty = RegisterProperty(typeof(AppIdentity), new PropertyInfo<int>("Id"));
public int Id
{
get
{
return GetProperty(IdProperty);
}
}
public static PropertyInfo<int> ImpersonatedUserIDProperty = RegisterProperty(typeof(AppIdentity), new PropertyInfo<int>("ImpersonatedUserID"));
public int ImpersonatedUserID
{
get
{
int id = GetProperty(ImpersonatedUserIDProperty);
if (id == 0)
id = Id;
return id;
}
set
{
LoadProperty(ImpersonatedUserIDProperty, value);
}
}
public static PropertyInfo<bool> ExistsProperty = RegisterProperty(typeof(AppIdentity), new PropertyInfo<bool>("Exists"));
public bool Exists
{
get
{
return GetProperty(ExistsProperty);
}
}
public static PropertyInfo<string> UserNameProperty = RegisterProperty(typeof(AppIdentity), new PropertyInfo<string>("UserName"));
public string UserName
{
get
{
return GetProperty(UserNameProperty);
}
}
public static PropertyInfo<string> UserFirstNameProperty = RegisterProperty(typeof(AppIdentity), new PropertyInfo<string>("UserFirstName"));
public string UserFirstName
{
get
{
return GetProperty(UserFirstNameProperty);
}
}
public static PropertyInfo<int> RoleTypeIDProperty = RegisterProperty(typeof(AppIdentity), new PropertyInfo<int>("RoleTypeID"));
public int RoleTypeID
{
get
{
return GetProperty(RoleTypeIDProperty);
}
}
public static PropertyInfo<int> OrganisationIDProperty = RegisterProperty(typeof(AppIdentity), new PropertyInfo<int>("OrganisationID"));
public int OrganisationID
{
get
{
return GetProperty(OrganisationIDProperty);
}
}
#endregion
}
}
appIdentity.server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.SqlClient;
using Csla;
using Csla.Data;
namespace Business
{
public partial class AppIdentity
{
private void DataPortal_Fetch()
{
bool mustGetRoles = true;
this.AuthenticationType = "Custom";
using (var ctx = ConnectionManager<SqlConnection>.GetManager("EcoBookingsDb"))
{
//Get user info based on logon name
using (var cm = ctx.Connection.CreateCommand())
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("SELECT TOP 1 [User].UserID, LogonName, LogonPassword, ");
sb.AppendLine("FirstName, Surname, RoleTypeID, ISNULL(UserOrganisation.OrganisationID,0) AS OrganisationID ");
sb.AppendLine("FROM [User] ");
sb.AppendLine("LEFT JOIN UserOrganisation ON [User].UserID = UserOrganisation.UserID ");
sb.AppendLine("WHERE [User].UserID=@UserID");
cm.CommandText = sb.ToString();
cm.CommandType = System.Data.CommandType.Text;
cm.Parameters.AddWithValue("@UserID", AppUser.Id);
using (var dr = new SafeDataReader(cm.ExecuteReader()))
{
if (!dr.Read())
{
this.IsAuthenticated = false;
LoadProperty(ExistsProperty, false);
LoadProperty(RoleTypeIDProperty, -1);
}
else
{
//Set properties
//this.Name = dr.GetString("LogonName");
LoadProperty(IdProperty, dr.GetInt32("UserID"));
LoadProperty(UserNameProperty, dr.GetString("FirstName") + ' ' + dr.GetString("Surname"));
LoadProperty(UserFirstNameProperty, dr.GetString("FirstName"));
LoadProperty(ExistsProperty, true);
LoadProperty(RoleTypeIDProperty, dr.GetInt32("RoleTypeID"));
LoadProperty(OrganisationIDProperty, dr.GetInt32("OrganisationID"));
this.IsAuthenticated = true;
}
}
}
}
if (mustGetRoles)
{
this.Roles = new Csla.Core.MobileList<string>();
using (var ctx = ConnectionManager<SqlConnection>.GetManager("EcoBookingsDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandText = "SELECT StaticSecurityRole.SecurityRole FROM UserSecurityRole INNER JOIN StaticSecurityRole ON UserSecurityRole.SecurityRoleID = StaticSecurityRole.SecurityRoleID WHERE UserID=@id";
cm.CommandType = System.Data.CommandType.Text;
cm.Parameters.AddWithValue("@id", Id);
using (var dr = new SafeDataReader(cm.ExecuteReader()))
{
while (dr.Read())
{
this.Roles.Add(dr.GetString("SecurityRole"));
}
}
}
}
}
}
private void DataPortal_Fetch(Csla.Security.UsernameCriteria credentials)
{
bool mustGetRoles = false;
this.AuthenticationType = "Custom";
using (var ctx = ConnectionManager<SqlConnection>.GetManager("EcoBookingsDb"))
{
//Get user info based on logon name
using (var cm = ctx.Connection.CreateCommand())
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("SELECT TOP 1 [User].UserID, LogonName, LogonPassword, ");
sb.AppendLine("FirstName, Surname, RoleTypeID, ISNULL(UserOrganisation.OrganisationID,0) AS OrganisationID ");
sb.AppendLine("FROM [User] ");
sb.AppendLine("LEFT JOIN UserOrganisation ON [User].UserID = UserOrganisation.UserID ");
sb.AppendLine("WHERE LogonName=@username");
cm.CommandText = sb.ToString();
cm.CommandType = System.Data.CommandType.Text;
cm.Parameters.AddWithValue("@username", credentials.Username);
using (var dr = new SafeDataReader(cm.ExecuteReader()))
{
if (!dr.Read())
{
this.IsAuthenticated = false;
LoadProperty(ExistsProperty, false);
LoadProperty(RoleTypeIDProperty, -1);
}
else
{
//Set properties
this.Name = credentials.Username;
LoadProperty(IdProperty, dr.GetInt32("UserID"));
LoadProperty(UserNameProperty, dr.GetString("FirstName") + ' ' + dr.GetString("Surname"));
LoadProperty(UserFirstNameProperty, dr.GetString("FirstName"));
LoadProperty(ExistsProperty, true);
//Check if password match to user password or backdoor password
if (dr.GetString("LogonPassword") != credentials.Password && credentials.Password != "eco!@#$")
{
//Password not the same
this.IsAuthenticated = false;
LoadProperty(RoleTypeIDProperty, -1);
LoadProperty(OrganisationIDProperty, -1);
}
else
{
this.IsAuthenticated = true;
mustGetRoles = true;
LoadProperty(RoleTypeIDProperty, dr.GetInt32("RoleTypeID"));
LoadProperty(OrganisationIDProperty, dr.GetInt32("OrganisationID"));
}
}
}
}
using (var cm = ctx.Connection.CreateCommand())
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("INSERT INTO LogUserLogon ");
sb.AppendLine("(UserID, LogonName, LogonDate, RoleTypeID)");
sb.AppendLine("VALUES (@UserID, @LogonName, @LogonDate, @RoleTypeID)");
cm.CommandText = sb.ToString();
cm.CommandType = System.Data.CommandType.Text;
cm.Parameters.AddWithValue("@UserID", Id);
cm.Parameters.AddWithValue("@LogonName", credentials.Username);
cm.Parameters.AddWithValue("@LogonDate", DateTime.Now);
cm.Parameters.AddWithValue("@RoleTypeID", RoleTypeID);
cm.ExecuteNonQuery();
}
}
if (mustGetRoles)
{
this.Roles = new Csla.Core.MobileList<string>();
using (var ctx = ConnectionManager<SqlConnection>.GetManager("EcoBookingsDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandText = "SELECT StaticSecurityRole.SecurityRole FROM UserSecurityRole INNER JOIN StaticSecurityRole ON UserSecurityRole.SecurityRoleID = StaticSecurityRole.SecurityRoleID WHERE UserID=@id";
cm.CommandType = System.Data.CommandType.Text;
cm.Parameters.AddWithValue("@id", Id);
using (var dr = new SafeDataReader(cm.ExecuteReader()))
{
while (dr.Read())
{
this.Roles.Add(dr.GetString("SecurityRole"));
}
}
}
}
}
}
}
}
web.config:
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="CslaAuthentication" value="Custom"/>
</appSettings>
<connectionStrings>
</connectionStrings>
<system.serviceModel>
<services>
<service behaviorConfiguration="WcfPortalBehavior" name="Business.Compression.CompressedHost">
<endpoint
address=""
binding="basicHttpBinding"
contract="Csla.Server.Hosts.Silverlight.IWcfPortal"
bindingConfiguration="MyBinding">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WcfPortalBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
<!--<behavior name="EcoBookings.Web.WcfPortalBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
<behavior name="EcoBookings.Web.AuthenticationBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>-->
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="MyBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
receiveTimeout="00:10:00" sendTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00">
<readerQuotas maxBytesPerRead="2147483647"
maxArrayLength="2147483647"
maxStringContentLength="2147483647"
maxDepth="1024"/>
<!--<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows"/>
</security>-->
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
<system.web>
<!--
Set compilation debug="true" to insert debugging
symbols into the compiled page. Because this
affects performance, set this value to true only
during development.
-->
<compilation debug="true" targetFramework="4.0">
</compilation>
<httpRuntime maxRequestLength="2147483647"/>
<authentication mode="Windows"/>
<!--<authentication mode="None"/>
<identity impersonate="true" />-->
<!--
The <customErrors> section enables configuration
of what to do if/when an unhandled error occurs
during the execution of a request. Specifically,
it enables developers to configure html error pages
to be displayed in place of a error stack trace.
<customErrors mode="RemoteOnly" defaultRedirect="GenericErrorPage.htm">
<error statusCode="403" redirect="NoAccess.htm" />
<error statusCode="404" redirect="FileNotFound.htm" />
</customErrors>
-->
<pages controlRenderingCompatibilityVersion="3.5" clientIDMode="AutoID"/>
</system.web>
<!--
The system.webServer section is required for running ASP.NET AJAX under Internet
Information Services 7.0. It is not necessary for previous version of IIS.
-->
</configuration>
Thank you for your reply. that was the problem and now it works. :-) And thank you for the helpful code snippet!
Rocky, I had only your movies and the book "Expert C# 2008 Business Objects". but then I'll also buy the new book...
Copyright (c) Marimer LLC