UnauthorizedAccessException : Invalid cross-thread access.

Topics: Prism v2 - Silverlight 2
Mar 6, 2009 at 12:50 AM
I am trying to access a WCF service using the interface generated by adding a service reference to my project. It works if I use the concrete class's MyMethodAsync method and subscribe to the competed event, but I'm trying to use the interface so I'm not tied to the concreate implementation. The interface has the BeginXXX and EndXXX methods, but I get an UnauthorizedAccessException when I update my model and raise the PropertyChanged event. 

What is the recommended method of updating the UI from a background thread? I've tried using Application.Current.RootVisual.Dispatcher but it throws the same exception when it tries to access RootVisual. So how am I supposed to do this, I don't see any examples in the documentation or on the web.
Mar 6, 2009 at 10:55 AM
Here's what I ended up doing: http://stackoverflow.com/questions/617377/decoupling-silverlight-client-from-service-reference-generated-class/618592#618592

See my detailed answer in the above link describing how I made a custom interface and then extended the proxy class using a partial class.
Mar 6, 2009 at 12:20 PM
Edited Mar 6, 2009 at 12:23 PM
If decoupling is your objective you might be interested in the UnityContrib project (no relation to UnityContributions) that I have in my http://www.CodePlex.com/SDMS application.   As you'll see from the first WebCast link on the home page I can configure, from the Website's Web.Config which implementation the WCF service should use for the service interface.  

You'll find the Presentation Tier's Business Logic Layer works off of an interface (decoupled from the Data Layer - the Data Layer need only to adhere to the interface)
Mar 6, 2009 at 5:26 PM
Thx, I'll check it out. But doesn't Prism support this scenario? I thought the whole point of the CAL was to create loosely-coupled, testible applications. The guidance doesn't seem to cover WCF and I can't seem to find anything concrete on the web.
Mar 6, 2009 at 6:13 PM
Edited Sep 4, 2009 at 7:19 PM

[developmentally] guidance doesn't seem to cover WCF and I can't seem to find anything concrete on the web.

Which is why I'm still investing time in the SDMS application (in the midst of two contracts - pulling back on open source).  SDMS utilization of WCF may not be "the" way but it is "a" way that works....  It is a way that is independent of the Data Layer  (WCF, L2S, EF, etc) on both the Presentation and Middle Tiers.  

There is no authoritivative source for Prism/Silverlight and WCF (not even the Silverlight Web Service team is providing guidance - see below).  Where John Papa is an authoritivative source for Silverlight and Data Access there is no one providing architectural guidance that doesn't fall outside of  Presentation -> WCF -> ServiceLayer -> BLL -> DAL -> Data.    The CompositeWPF/Prism changed all of the rules - the reality is that both the Presentation and Middle tier's should have business logic and data access layers, particularly since we can reuse services in Silverlight modules.   Case in point, Silverlight can benefit from Isolated Storage opening up scenarios where your Prism application could chose a local cached data source as an option limiting the round-trips.

(steps off his soap box hoping Microsoft is listening)

Bill

-----Original Message-----
From: Yavor Georgiev
Sent: Monday, January 12, 2009 12:05 PM
To: bill@global-webnet.com
Cc: CDF Silverlight Customer Issues
Subject: RE: (Silverlight Web Services Team) : SLSvcUtil - what is recommended P&P?

Hi Bill,

Thanks for your note.

I understand the scenario you are encountering in your enterprise app around managing config files. This is a common customer request and a command-line tool like svcutil is being considered in the next version of Silverilght.

Unfortunately we don't have any additional tips we can provide at this point. Please continue to follow our blog for SL3-related updates.

Thanks,
-Yavor

-----Original Message-----
From: bill@global-webnet.com [mailto:bill@global-webnet.com]
Sent: Wednesday, January 07, 2009 7:21 PM
To: Yavor Georgiev
Subject: (Silverlight Web Services Team) : SLSvcUtil - what is recommended P&P?
Importance: High

Can the team provide guidance for consuming WCF service for enterprise level applications?   My initial efforts were somewhat frustrating as the Silverlight forums have you going in circles looking for a SLSvcUtil that doesn't exist, or SVCUtil flags that supposedly support Silverlight (that no one can reference).

The following blog highlights an issue with using Prism/CompositeWPF and Silverlight - the main assembly has to have a copy of the ServiceReferences.ClientConfig referenced in a module (separate assembly): 

http://www.global-webnet.net/blogengine/post/2009/01/03/PrismWCF-Cannot-find-ServiceReferencesClientConfig-in-xap-application-package.aspx

The above provides a simple solution for a single module that consumes a single WCF service.   When we have 20+ modules, configuration promises to be quite the nightmare complicated by a cyle that has the solution moving through development, staging and production environments.

"Add Web Service" doesn't seem to be a viable solution.

Your guidance and assistance will be appreciated as we have numerous sprints planned throughout the year that will be based on the infrastructure I provide; as an Independent Contractor I have a large responsibility to get this done right.

Bill Kratochvil
Global Webnet, LLC
Blog: http://www.Global-webnet.net/BlogEngine

Mar 6, 2009 at 7:59 PM
Thanks for the details, now I understand the situation better. I'm still surprised that this wasn't addressed before releasing Silverlight support for Prism. I'm a bit disappointed as well that this is going to require waiting for SL3. I guess I'll need to go thru your samples in detail as well. I'm not looking for multi-targeting support, I just want an SL app that uses WCF and is maintainable and testable.
Mar 6, 2009 at 10:46 PM
[developmentally] I'm not looking for multi-targeting support, I just want an SL app that uses WCF and is maintainable and testable.

I don't think they are mutually exclusive - I believe you may want/need multi-targeting support.   Let me explain by example - I just spent the last couple of hours updating the SDMS application so that the Modules folder is supported under both Desktop and Silverlight.  Why?   "maintainable and testable".   I created a Unit Test for you and checked everything in (been really wanting to do this for a while and this gave me good reason to).

The key point here is that the "only" code that will be different will be the XAML (Silverlight/WPF) and the actual WCF Service call.  I did however create my Desktop WCF Service using Async communications so you won't find any SILVERLIGHT conditional statements anywhere in the Business Logic Layer or Data Layer (they are one and the same code for both sides).   I should give a plug for the Project Linker (blogged about on my blog site w/webcast); all my time was spent creating empty WPF views and implementing the interface on them.

[TestMethod]

public void TestMethod1()

{

    // IModule does all of the heavy lifting - configures all interfaces

    // so we'll just use it to set things up.

    IModule module = Container.Resolve<IModule>();

    module.Initialize();

 

    // Resolve the EmployeeList Presenter

    EmployeeListPresenter MockView = Container.Resolve<EmployeeListPresenter>();

 

    // Give WCF Service a chance to complete

    Thread.Sleep(2000);

 

    // Cast so we can easily access presentation model

    EmployeePresentationModel model = (EmployeePresentationModel) MockView.Model;

 

    Assert.AreEqual(3, model.EmployeeList.Count, "Employee list should have three records!");

}


Note we can put the Testing thread to sleep :)  I just tested everything short of the UI which is databound to the presentation model (nothing to test in the view) all the way through the WCF Service and back.  Since my PresentationModel implements INotifyPropertyChanged I can rest assured my View will work (assuming I did my Binding correctly).

Let's see what IModule was up to (showing the effectiveness of multi-targeting)

public class ModuleEmployee : IModule

{

    // For class use

    private readonly IUnityContainer container;

    private readonly IRegionViewRegistry regionViewRegistry;

 

    /// <summary>

    /// Constructor : Setup class

    /// </summary>

    /// <param name="container"></param>

    /// <param name="regionViewRegistry"></param>

    public ModuleEmployee(IUnityContainer container,

        IRegionViewRegistry regionViewRegistry)

    {

        this.container = container;

        this.regionViewRegistry = regionViewRegistry;

    }

 

    public void Initialize()

    {

        RegisterViewAndServices();

 

        // EmployeeModule - Views folder

        regionViewRegistry.RegisterViewWithRegion("MainRegion",

            () => container.Resolve<EmployeeMainPresenter>().View);

 

        regionViewRegistry.RegisterViewWithRegion("frmCaption",

            () => container.Resolve<frmCaptionPresenter>().View);

 

        regionViewRegistry.RegisterViewWithRegion("frmEmployeeList",

            () => container.Resolve<EmployeeListPresenter>().View);

 

        regionViewRegistry.RegisterViewWithRegion("TabInformation",

            () => container.Resolve<EmployeeInformationPresenter>().View);

 

        regionViewRegistry.RegisterViewWithRegion("TabAssigned",

           () => container.Resolve<EmployeeAssignedPresenter>().View);

 

        regionViewRegistry.RegisterViewWithRegion("TabInWork",

           () => container.Resolve<EmployeeInWorkPresenter>().View);

 

        regionViewRegistry.RegisterViewWithRegion("frmStatus",

            () => container.Resolve<frmStatusPresenter>().View);

 

    }

 

    private void RegisterViewAndServices()

    {

        container.RegisterType<IEmployeeMainView, EmployeeMainView>()

 

            // Layers

            .RegisterType<IEmployeeProviderBLL,EmployeeProviderBLL>()

            .RegisterType<IEmployeeProviderDAL,EmployeeProviderDAL>()

 

            // Views

            .RegisterType<IfrmStatusView, frmStatusView>()

            .RegisterType<IfrmCaptionView, frmCaptionView>()

            .RegisterType<IEmployeeListView, EmployeeListView>()

            .RegisterType<IEmployeeListView, EmployeeListView>()

            .RegisterType<IEmployeeInWorkView, EmployeeInWorkView>()

            .RegisterType<IEmployeeAssignedView, EmployeeAssignedView>()

            .RegisterType<IEmployeeInformationView, EmployeeInformationView>()

 

            // Services

            .RegisterType<IEmployeeService, EmployeeService>()

 

            // Models

            .RegisterType<IEmployeePresentationModel, EmployeePresentationModel>(

                            new ContainerControlledLifetimeManager());

    }

}

}

<!--EndFragment-->
It did some pretty heavy lifting which tells me everything that will be executed during Silverlight runtime - works. 

The following is the Presenter, which is responsible for updating the Presentation Model (which the view is observing).  You can see that my Desktop Unit Test effectively exercises many, if not all, logic within the process.   Silverlight unit testing is done in a browser...  I'd rather take this approach.

Hope this helps in your quest to finding an architecture that works for you!

Bill

public class EmployeeListPresenter : PresenterBase<IEmployeeListView>

{

    readonly IEmployeeService employeeService;

    readonly IEventAggregator aggregator;

    readonly IEmployeePresentationModel model;

 

    /// <summary>

    /// Constructor : setup class

    /// </summary>

    /// <param name="container"></param>

    /// <param name="view"></param>

    public EmployeeListPresenter(

        IEmployeeListView view,

        IEmployeePresentationModel model,

        IUnityContainer container,

        IEventAggregator aggregator,

        IEmployeeService service) : base(view,model,container)

    {

        this.aggregator = aggregator;

        this.employeeService = service;

        this.model = model;

 

        // Subscribe to ListBoxChanged event and

        aggregator.GetEvent<ListBoxChangedEvent>().Subscribe(ListBoxChangedEventHandler, true);

        aggregator.GetEvent<EmployeeEvent>().Subscribe(EmployeeEventHandler, true);

 

        // Async call to service to populate employee list.  The EmployeeListEventHandler

        // will be called when data is received

        employeeService.GetEmployeeList();

    }

 

    /// <summary>

    /// Subscribed to in constructor - updates the model's SelectedEmployee property every

    /// time a new employee is selected

    /// </summary>

    /// <param name="args"></param>

    private void ListBoxChangedEventHandler(SelectionChangedEventArgs args)

    {

        model.SelectedEmployee = args.AddedItems[0] as Employee_Data;

 

        StatusBarEvent sbEvent = aggregator.GetEvent<StatusBarEvent>();

        if (sbEvent != null)

            aggregator.GetEvent<StatusBarEvent>().Publish(

                new StatusBarData

                {

                    Message = string.Format("You clicked {0}", model.SelectedEmployee.DisplayValue),

                    Panel = StatusPanel.Left

                });

    }

 

    /// <summary>

    /// Handler for when Employee list is returned by service call to

    /// GetEmployeeList()

    /// </summary>

    /// <param name="args"></param>

    private void EmployeeEventHandler(EmployeeEventArgs args)

    {

        model.EmployeeList = args.EmployeeList;

    }

 }

<!--EndFragment-->











<!--EndFragment-->
Mar 7, 2009 at 12:14 AM
Wow, thanks!!! I must say, I appreciate your help. I figured out my original problem - just didn't understand Dispatcher and how/when I could use it. I just needed to register a reference to the shell's Dispatcher in the container - now I can access it anywhere. So now I'm able to just use the service client's interface instead of being dependent on the proxy class generated. This should allow me to test in isolation. I actually took it a step further and created my own interface (exactly the same as the generated one) and placed it in a separate module along with all my other interfaces. My goal is that the modules can reference the Interfaces project and won't need to reference each other. 

As for the archtecture, I can tell yours is really well thought out and fits well with Prism, but for the moment what I have meets all my needs. I will need to incorporate something like your architechture down the road, but I'm a bit behind and will just be moving forward with what I've got at this point. Again, thanks. I've really rarely ever had the kind of response I've gotten from you.