Skip to main content
Home Forums Silverlight Programming WCF RIA Services Exception: The DomainContextType is null or invalid and there are no contexts generated from AuthenticationBase<T>
24 replies. Latest Post by sethian on November 5, 2009.
(0)
sorenhk
Member
15 points
5 Posts
07-19-2009 7:57 AM |
Hello
I'm getting the following exception when calling the AuthenticationService.Login method:Message: Unhandled Error in Silverlight 2 Application The DomainContextType is null or invalid and there are no contexts generated from AuthenticationBase<T>. at System.Windows.Ria.ApplicationServices.AuthenticationService.Login(LoginParameters parameters, Action`1 completeAction, Object userState) at Admin.LoginModule.Services.LoginService.TryLogin(String username, String password, Boolean rememberMe)This is the method call in my TryLogin method:
RiaContext.Current.Authentication.Login(new LoginParameters(username, password), loginCompleted, null);
In App.xaml:
1 <Application.ApplicationLifetimeObjects>2 <data:RiaContext>3 <data:RiaContext.Authentication>4 <riaapps:FormsAuthentication/>5 </data:RiaContext.Authentication>6 </data:RiaContext>7 </Application.ApplicationLifetimeObjects>
In AuthenticationService.cs:
1 [EnableClientAccess]2 public class AuthenticationService : AuthenticationBase<User>3 {4 [Insert]5 public void AddUser(User user)6 {7 // Some code8 }9 10 [Delete]11 public void DeleteUser(User user)12 {13 // Some code14 }15 16 [Query]17 public IEnumerable<User> GetUsers()18 {19 // Some code20 }21 22 [ServiceOperation]23 public void ResetPassword(User user)24 {25 // Some code 26 }27 28 [Query]29 public IEnumerable<Role> GetRoles()30 {31 // Some code32 }33 34 [Delete]35 public void DeleteRole(Role role)36 {37 // Some code38 }39 }
My User-class implements IUser but not the other interfaces used in the sample (I hope that doesn't matter).
I've checked the generated code and it does have an AuthenticationContext that derives from AuthenticationBase
Any help would be much appreciated! Thanks
07-19-2009 9:23 AM |
I've overrided the ValidateUser and GetAuthenticatedUser methods and made User extend the UserBase class which seemed to make login work in a newly created business application (I'm trying to isolate the problem). I'm still getting the above exception in my "real" project though and I have absolutely no idea why.
kylemc
Participant
1482 points
255 Posts
07-20-2009 11:56 AM |
Is your AuthenticationContext being generated into the main application assembly or a class library? FormsAuthentication and WindowsAuthentication will only "find" contexts generated into the main assembly. If you're generating it somewhere else, there are a couple options.
1) Set FormsAuthentication.DomainContext in code to a new instance of the type.
2) Set FormsAuthentication.DomainContextType in xaml to the full name of the type if it is in the main assembly.
3) Set FormsAuthentication.DomainContextType in xaml to the assembly-qualified name of the type if it is in a class library.
Kyle
ScottNZ
47 points
25 Posts
07-22-2009 2:07 AM |
Hi Kyle,
Can you post a quick example of the xaml/code for setting FormsAuthentication.DomainContextType or .DomainContext? And where/when should this be set?
I've got the same exception as sorenhk at the top of this thread, and I'm just not seeing the solution. My AuthenticationContext is being generated in a class lib.
Cheers,Scott
07-22-2009 4:14 AM |
Hello Scott
This solved it for me:
In you App.xaml:
1 <Application.ApplicationLifetimeObjects> 2 <local:RiaContext> 3 <local:RiaContext.Authentication> 4 <appsvc:FormsAuthentication DomainContextType="Web.Services.AuthenticationContext, Admin.Data, Version= 1.0.0.0"/> 5 <!-- [Optional] <appsvc:WindowsAuthentication/>--> 6 </local:RiaContext.Authentication> 7 </local:RiaContext> 8 </Application.ApplicationLifetimeObjects>
Where the namespace "local" is where you defined your RiaContext (this wont get generated in your class library, so you will have to write the code yourself and place it outside of the generated file (which will be overwritten the next time you build))
appsvc is: clr-namespace:System.Windows.Ria.ApplicationServices;assembly=System.Windows.Ria
Check the generated file in your RIA class library for the namespace that the AuthenticationContext is placed in.
Admin.Data is the name of my RIA class library assembly.
I hope this helps you :-)
/SorenHK
07-23-2009 2:18 AM |
Hi SorenHK,
Thanks very much for that--it was just what I was looking for. Unfortunately I was not able to solve my issue that way. I was trying to add the RiaContext code from a simple simple, sample solution into my multi-assembly solution, and there were other problems associated with that.
My biggest problem was due to the fact that both my data-access RIA service classes and my user authentication service classes were in the same middle tier web project. In addition to that, I was trying to add a RIA link from a Silverlight class library project. Because the RIA link was not in a SL Application project, the RiaContext User code was not being generated.
In order to solve it, I had to a) move the RIA data access service code from my web project into a separate pair of projects per the RIA Services Class Library template, b) replace the RIA Link in my SL class library with a reference to "client" project produced by the RIA Class Library template, and c) add a RIA Link from my SL application project to the middle-tier web project containing the RIA user authentication service classes.
After eight hours of that and very nearly giving up at least twice, I finally was able to access the RIA DataContext classes from my SL class library as well as benefit from the RIA generated RiaContext.* user authentication/authorisation services in my SL Application project.
Scott
sethian
35 points
38 Posts
07-29-2009 7:00 PM |
Hi and thanks for all the good info! Without this post I would have been completely lost. I do want to add a bit more though, although it might be redundant.
Following the design pattern in 19.3.3 of the RIAServicesOverview.docx, I decided to move my RIA DAL to a RIA Services class library. Having completed that, I removed the RIA link from my SL app to the main app.web. This of course caused the RIA Authentication to break as those services were still in the main app.web.
No problem, I created a second RIA Services class library for Authentication and UserRegistration. Yes, I could have simply recreated the RIA link from my SL app to my app.web, but that is not the recommened method in the Overview docudment (see section 19.3.4).
Now that my AuthenticationService and UserRegistrationService were in a RIA Lib, registration broke with the exception posted in this thread Subject.
The solution was two fold (I'm simply restating what's in this thread in so many words). First, you must create the RiaContext. This is done manually in the Silverlight portion of the RIA Library that contains your Authentication and UserRigistration services. So for example, I moved AuthenticationService.cs, UserInformation,cs and UserRegistrationService.cs into a new RIA lib called "MyLibrary.Security.Web". I put these files in a Services folder. Then within the Silverlight side of the Library (MyLibrary.Security) I placed the following RiaContext.cs file:
using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web.Ria.Data; using System.Windows.Ria.Data; using MyLibrary.Security.Web.Services; namespace MyLibrary.Security { /// <summary> /// Context for the RIA application. /// </summary> /// <remarks> /// This context extends the base to make application services and types available /// for consumption from code and xaml. /// </remarks> public sealed partial class RiaContext : System.Windows.Ria.RiaContextBase { #region Extensibility Method Definitions /// <summary> /// This method is invoked from the constructor once initialization is complete and /// can be used for further object setup. /// </summary> partial void OnCreated(); #endregion /// <summary> /// Initializes a new instance of the RiaContext class. /// </summary> public RiaContext() { this.OnCreated(); } /// <summary> /// Gets the context that is registered as a lifetime object with the current application. /// </summary> /// <exception cref="InvalidOperationException"> is thrown if there is no current application, /// no contexts have been added, or more than one context has been added. /// </exception> /// <seealso cref="Application.ApplicationLifetimeObjects"/> public new static RiaContext Current { get { return ( (RiaContext)( System.Windows.Ria.RiaContextBase.Current ) ); } } /// <summary> /// Gets a user representing the authenticated identity. /// </summary> public new User User { get { return ( (User)( base.User ) ); } } } }
Next, you must update the App.xaml in the silverlight application to use the new AuthenticationService in your RIA Library. Here's my sample code:
<Application x:Class="MDTM.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:app="clr-namespace:MyLibrary.Security;assembly=MyLibrary.Security" xmlns:appsvc="clr-namespace:System.Windows.Ria.ApplicationServices;assembly=System.Windows.Ria" > <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Assets/Styles.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> <Application.ApplicationLifetimeObjects> <app:RiaContext> <app:RiaContext.Authentication> <appsvc:FormsAuthentication DomainContextType="MyLibrary.Security.Web.Services.AuthenticationContext, MyLibrary.Security, Version=1.0.0.0"/> <!--<appsvc:WindowsAuthentication/>--> </app:RiaContext.Authentication> </app:RiaContext> </Application.ApplicationLifetimeObjects> </Application>
The important part is the DomainContextType. The first part must specify the full class name of the AuthenticationService (of course, called AuthenticationContext when it's renamed by RIA), the second part the RIA Library name. This gave me problems for a bit of time till I got it right.
Paul
07-29-2009 7:35 PM |
Hey Paul,
Great post--it very clearly sums up the proper solution. I'm going to take my solution that one step further and move the Authentication services into a RIA library as well. My current solution which has a RIA Link from the SL application project suffers from the problem that the RiaContext object is only available from the SL application assembly. My "Infrastructure" assembly which the SL application assembly references is unable to reference the RiaContext.* authentication services.
07-30-2009 12:25 PM |
One other thing I forgot to mention, converting a Silverlight Business Application to use an external RIA Service Library with Authentication also posed a lot of issues with References necessary in the RIA Service Library. I simply copied the code from the primary app.web (AuthenticationService.cs, etc), into the RIA Library, then added System.Web.
Also, you must update the using statements in your silverlight application. Here are mine
using MyLibrary.RIA; using MyLibrary.Security.Web.Services; using MyLibrary.Security;
rcustance
16 Posts
08-04-2009 7:07 PM |
Scott,
Did you manage to sort this? I to have a situation where I would like to reference the RiaContext from a infrastructure asembly.
Thanks
Richie
08-05-2009 12:16 AM |
Richie,
It's the next item on my list, but I haven't gotten there yet. I believe it would/should work if one does the following:
Did I miss anything? I have to wonder what changes the next CTP/release of RIA Services will bring. Does anyone know if the "RiaContext class is only generated in a SL Application project" behaviour/restriction is likely to change soon? If so, that would simplify this problem. Let us know if you get it going in your infrastructure project.
Good luck-Scott
Aquilax
43 points
37 Posts
08-28-2009 11:25 AM |
I had the same problem and with a little bit of reflection I found the solution. The DomainAuthentication object is looking for the DomainContext inside the Application assembly (DomainAuthentication.InitializeDomainContext(){...}), if you have the RIA generating the client code in a separate assembly the DomainAuthentication will never find the DomainContext.
There are two solutions:
1) Copy paste the the AuthenticationContext class from the generated code in the silverlight library into the application
2) Set the DomainContext manually in code:
private void Application_Startup(object sender, StartupEventArgs e){ ((DomainAuthentication)RiaContext.Current.Authentication).DomainContext = new [SilverlightProjectName].Web.AuthenticationContext(); this.Resources.Add("RiaContext", RiaContext.Current); this.RootVisual = new MainPage();}
Blorf
24 points
56 Posts
09-02-2009 6:50 PM |
Excellent thread. I have a separate RIA Library for authentication and have I have everything working with the exception that my User object is not filled in on the client. I setup the RiaContext like sethian suggested and used the full assembly qualified name to set the DomainContextType in the App.xaml
When I break in the authentication domain service on the server side I see the User object I'm returning is filled with data, but when I break in the operation completion event handler for the Login operation the RiaContext.Current.User looks like the result of a "new User()" with none of the data I filled in on the server side.
Did I miss hooking something up that gets the User returned from the authentication domain service into the RiaContext.Current.User ?
Any ideas on where to start looking for why User is not filled in on the client ?
09-03-2009 7:35 PM |
Check the type of the returned User in the login completion. It should be something like MDTM.Security.Web.Services.User, which is defined in the server side AuthenticationService.cs . Authentication is clearly working, it just seems the wrong User class is attached to the RiaContext.
My first thought is that you have a namespace incorrect somewhere.
09-03-2009 8:20 PM |
I have my own test project so the names are slightly different, but it is the equivalent of what you mention. The type in my login completion of the RiaContext.Current.User is MyAuthenticationLib.Web.User. That is defined in my authentication service (MyAuthenticationService.cs) in the web portion of the RIA Class Lib (MyAuthenticationLib). It is defined as follows:
namespace MyAuthenticationLib.Web { [EnableClientAccess ()] public class MyAuthenticationService : LinqToEntitiesDomainService<MyAuthDBEntities>, IAuthentication<User> { .... implementation ... } public partial class User : IUser { #region IUser Members public IEnumerable<string> Roles { get { throw new NotImplementedException (); } set { throw new NotImplementedException (); } } #endregion }
The Name property is not implemented because my User entity from the EF model has a Name property already.
Then in the silverlight part of the RIA Class Lib (MyAuthenticationLib) I have an RiaContext class that is basically the same as mentioned earlier, so it makes the User property a type of User which comes from the web (server) side of the RIA Class lib. Here is what I have for RiaContext:
namespace MyAuthenticationLib { public sealed partial class RiaContext : System.Windows.Ria.RiaContextBase { #region Extensibility Method Definitions partial void OnCreated (); #endregion public RiaContext () { this.OnCreated (); } public new static RiaContext Current { get { return ((RiaContext)(System.Windows.Ria.RiaContextBase.Current)); } } public new User User { get { return ((User)(base.User)); } } }}
Any ideas ?
09-04-2009 11:41 AM |
Never mind, it was a UTS (user too stupid) error.
In the Login service method I was just returning a new User() on successful login like this - "return new User() { Name=userName }" because it was quick.
I guess I thought the real line of "return Context.Users.First ( user => user.Name == userName )" was too much trouble.
Once I returned a real entity the User comes back filled in just fine and the IsAuthenticated is set correctly.
usna91
8 points
8 Posts
09-16-2009 4:45 PM |
Great thread and guidance thanks! I'm combining Prism with RIA and I've split a lot of my functionality into separate modules -- so needless to say having my Authentication service and data access logic in the "shell" module/assembly and then having to reference that assembly in all my other modules would be a poor solution and sort of defeat the purpose of using Prism.
I've split everything out into a separate Authentication web service and SL Class. Everything compiles and runs....but when I actually try to use the Login function on the base Authentication service, I get an InvalidOperationException with a "resource not found" message.
I suspect it might be to do with where the Uri used by the base AuthenticationContext is looking. On my machine its:
"DataService.axd/SecurityService-Web-AuthenticationService/"
The actual Dataservice.axd reference is still stored in my base Web app web config file.
Did you add a web or app config file to your security.web.services project or otherwise adjust the dataservice.axd entry in your main web app? I know I'm close and its driving me nuts!!!! Hopefully the release version of RIA resolves some of these issues as I hate having to do all this config file chicanery.
thanks
09-16-2009 5:03 PM |
I'm not sure if this will fix your problem, but try adding these elements in your Web.config:
<system.web>
<httpHandlers>
<add path="DataService.axd" verb="GET,POST" type="System.Web.Ria.DataServiceFactory, System.Web.Ria, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false"/>
</httpHandlers>
</system.web>
and:
<system.webServer>
<handlers>
<add name="DataService" verb="GET,POST" path="DataService.axd" type="System.Web.Ria.DataServiceFactory, System.Web.Ria, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
</handlers>
</system.webServer>
I hope this helps.
09-16-2009 5:07 PM |
Thanks, Soren. I already had the first but not the second. Didn't work. One thing did change, though. Now instead of an InvalidOperationException I get an EntityOperationException at the same point. Same error message. Resource not found....
09-16-2009 6:20 PM |
Still looking at the Uri defined by my Ria class AuthenticationContext -- I sniffed the login call using Fiddler and it goes to:
/ClientBin/DataService.axd/SecurityService-Web-AuthenticationService/Login HTTP/1.1
Is this the right path?
Would appreciate any guidance.....
09-17-2009 12:47 AM |
Sorted it out finally. I was missing a reference from my main Web app to my SecurityService.Web library. I'd somehow managed to reference the Silverlight Class library instead....
I'm liking this ability! But man, it was a pain to configure....
dabcabc
28 Posts
09-29-2009 5:58 AM |
Slightly different issue here - I can fetch my user, etc fine, however I am trying to perform an update to a user - I remove some associated entities and create some new ones, however when I call:
RiaContext.Current.Authentication.SaveUser(completeOperation, null);
I can see an error (EntityOperationException) has occured from within the completeOperation however the InnerException is null. Any ideas where to start with this as I cannot find any mention of problems with this anywhere :(
WinFxGuy
14 points
10-28-2009 10:02 AM |
sethian: Hi and thanks for all the good info! Without this post I would have been completely lost. I do want to add a bit more though, although it might be redundant. Following the design pattern in 19.3.3 of the RIAServicesOverview.docx, I decided to move my RIA DAL to a RIA Services class library. Having completed that, I removed the RIA link from my SL app to the main app.web. This of course caused the RIA Authentication to break as those services were still in the main app.web. No problem, I created a second RIA Services class library for Authentication and UserRegistration. Yes, I could have simply recreated the RIA link from my SL app to my app.web, but that is not the recommened method in the Overview docudment (see section 19.3.4). Now that my AuthenticationService and UserRegistrationService were in a RIA Lib, registration broke with the exception posted in this thread Subject. The solution was two fold (I'm simply restating what's in this thread in so many words). First, you must create the RiaContext. This is done manually in the Silverlight portion of the RIA Library that contains your Authentication and UserRigistration services. So for example, I moved AuthenticationService.cs, UserInformation,cs and UserRegistrationService.cs into a new RIA lib called "MyLibrary.Security.Web". I put these files in a Services folder. Then within the Silverlight side of the Library (MyLibrary.Security) I placed the following RiaContext.cs file: using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web.Ria.Data; using System.Windows.Ria.Data; using MyLibrary.Security.Web.Services; namespace MyLibrary.Security { /// <summary> /// Context for the RIA application. /// </summary> /// <remarks> /// This context extends the base to make application services and types available /// for consumption from code and xaml. /// </remarks> public sealed partial class RiaContext : System.Windows.Ria.RiaContextBase { #region Extensibility Method Definitions /// <summary> /// This method is invoked from the constructor once initialization is complete and /// can be used for further object setup. /// </summary> partial void OnCreated(); #endregion /// <summary> /// Initializes a new instance of the RiaContext class. /// </summary> public RiaContext() { this.OnCreated(); } /// <summary> /// Gets the context that is registered as a lifetime object with the current application. /// </summary> /// <exception cref="InvalidOperationException"> is thrown if there is no current application, /// no contexts have been added, or more than one context has been added. /// </exception> /// <seealso cref="Application.ApplicationLifetimeObjects"/> public new static RiaContext Current { get { return ( (RiaContext)( System.Windows.Ria.RiaContextBase.Current ) ); } } /// <summary> /// Gets a user representing the authenticated identity. /// </summary> public new User User { get { return ( (User)( base.User ) ); } } } } Next, you must update the App.xaml in the silverlight application to use the new AuthenticationService in your RIA Library. Here's my sample code:<Application x:Class="MDTM.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:app="clr-namespace:MyLibrary.Security;assembly=MyLibrary.Security" xmlns:appsvc="clr-namespace:System.Windows.Ria.ApplicationServices;assembly=System.Windows.Ria" > <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Assets/Styles.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> <Application.ApplicationLifetimeObjects> <app:RiaContext> <app:RiaContext.Authentication> <appsvc:FormsAuthentication DomainContextType="MyLibrary.Security.Web.Services.AuthenticationContext, MyLibrary.Security, Version=1.0.0.0"/> <!--<appsvc:WindowsAuthentication/>--> </app:RiaContext.Authentication> </app:RiaContext> </Application.ApplicationLifetimeObjects> </Application> The important part is the DomainContextType. The first part must specify the full class name of the AuthenticationService (of course, called AuthenticationContext when it's renamed by RIA), the second part the RIA Library name. This gave me problems for a bit of time till I got it right. Paul
I followed exactly the way mentioned above, but getting the following problems. The only difference is my library name is TMSLibrary.
1. At the using statement "using TMSLibrary.Security.Web.Services;"
The type or namespace name 'Web' does not exist in the namespace 'TMSLibrary.Security' (are you missing an assembly reference?)
2. At the line "return ((User)(base.User));"
TMSLibrary.Security.RiaContext.User' is a 'property' but is used like a 'type'
Any ideas???? Thanks in advance.
Jean-Pie...
27 points
31 Posts
11-04-2009 4:12 PM |
mmm. I got all of it to work, i.e. I can log in against my athentication service from a particular silverlight application which references the RIA Class Library. However, when I navigate to a different appplication, the RIAContext seems to be new, and I am no longer logged in. How can I get the Identity to persist across applications?
11-05-2009 5:58 PM |
Along the same lines, when a user pressed F5 or refreshes the browser, I am logged out. Is there a way to refresh the silverlight app but stay logged in?