I've setup a site with forms authentication and AspNetCompatibility enabled. The actual client is a silverlight application, and works fine, however I want to unit test the application separately using normal .net to exercise the service (live system for methods without side-effects). However, when I stop using Silverlight and start using full .net it doesn't remain authenticated
In a web service I have:
[OperationContract]
public bool Login(string Username, string Password, bool isPersistent)
{
if (Membership.ValidateUser(Username, Password))
{
FormsAuthentication.SetAuthCookie(Username, isPersistent);
return true;
}
else
{
return false;
}
}
[OperationContract]
public bool IsLoggedIn()
{
return HttpContext.Current.User.Identity.IsAuthenticated;
}
Then in a test method on the client I call it like so:
Assert.IsTrue(Client.Login("MyUsername","MyPassword", true));
Assert.IsTrue(Client.IsLoggedIn());
The client is an instance of the automatically generated ServiceReference client for .net. The first assertion passes but the second one fails, i.e. from one method call to the next it stops being logged in. A similar method in the silverlight application would pass.
How can I make normal .net behave correctly as silverlight would? Is there just a better way of configuring client/service for full .net?
Aditional Info Requested
Service Config:
<services>
<service behaviorConfiguration="MyBehaviour" name="SSCCMembership.Web.Services.LoginService">
<endpoint address="" binding="customBinding" bindingConfiguration="customBindingBinary"
contract="SSCCMembership.Web.Services.LoginService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<bindings>
<customBinding>
<binding name="customBindingBinary">
<binaryMessageEncoding />
<httpTransport />
</binding>
</customBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
Authentication Config:
<authentication mode="Forms" />
<membership defaultProvider="OdbcProvider">
<providers>
<clear />
<add name="OdbcProvider" type="SSCCMembership.Web.SimpleMembershipProvider" applicationName="/SSCCMembership" requiresUniqueEmail="false" connectionStringName="mainConn" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" writeExceptionsToEventLog="true" />
</providers>
</membership>
I then use the following to construct the client in WPF
public static T LoadService<T>(string URI, Func<CustomBinding, EndpointAddress, T> F)
{
try
{
Uri U = new Uri(new Uri(Root), URI);
BinaryMessageEncodingBindingElement binary = new BinaryMessageEncodingBindingElement();
HttpTransportBindingElement transport;
if (U.Scheme == "http")
transport = new HttpTransportBindingElement();
else if (U.Scheme == "https")
transport = new HttpsTransportBindingElement();
else
throw new Exception(U.Scheme + " is not a recognised URI scheme");
transport.MaxBufferSize = int.MaxValue;
transport.MaxReceivedMessageSize = transport.MaxBufferSize;
transport.AllowCookies = true;
CustomBinding binding;
binding = new CustomBinding(binary, transport);
EndpointAddress address = new EndpointAddress(U);
return F(binding, address);
}
catch (Exception)
{
return default(T);
}
}
Which I call like:
var Client = LoadService(ServiceLocation, (b,e)=>new LoginServiceClient(b,e));
I had this same type of problem and ended up just implementing the WCF Authentication Services... The documentation was straight forward and it works great with the ASP.NET forms auth provider.
http://msdn.microsoft.com/en-us/library/bb386582.aspx
Change your
IsLoggedIn()
method to reference theServiceSecurityContext
instead ofHttpContext
:I think the main problem you are having is due to the context that each application runs in.
A Silverlight application runs in the context of the web-page it's hosted in - and thus, can maintain session info, cookies, and all sorts of other things that you don't need to manually worry about.
As soon as you connect with an application running outside of the browser, your context (as far as asp.net is concerned) has changed. Have you tried enabling/installing the silverlight application out-of-browser to see if you have the same errors?
One way to work around this is to use the Silverlight Unit Test project and connect that to your web service for testing. (I have successfully done this with enterprise silverlight apps for the company I work for) The silverlight unit test project results in a silverlight app that can be hosted on a web page, and run from there - in the same context as any other silverlight app, as far as ASP.net is concerned, making your web-service calls much less likely to fail due to context.
Check out the Silverlight Unit Test Famework Homepage for more info...