Running WCSF on IIS 7 (integrated mode)
December 1st, 2009
If you host a WCSF application on IIS 7 (integrated mode), you will notice that the application throws an exception on its first request (System.Web.HttpException: Request is not available in this context).
This is because when the Application_Start method of the WebClientApplication class calls the GetConfiguration method of the WebConfigModuleInfoStore class, it requires access to the HttpContext.Request that is not yet available at this point of the application’s life cycle.
That said, I will show you how to workaround it without rebuilding the CWAB and taking advantage of Dependency Injection in just three simple steps:
- Copy the class named WebConfigModuleInfoStore under the project CompositeWeb into your main Web application, then rename it to WebConfigModuleInfoStoreExtended.
- In the method GetConfiguration paste the following code:
private static System.Configuration.Configuration GetConfiguration(string configFilePath) { System.Configuration.Configuration configuration; HttpContext context = HttpContext.Current; if (context == null) { configuration = GetConfigurationForCustomFile(configFilePath); } else { configuration = WebConfigurationManager.OpenWebConfiguration(HttpRuntime.AppDomainAppVirtualPath + "/" + configFilePath.Substring(HttpRuntime.AppDomainAppPath.Length)); } return configuration; }
- In your main Web application in the Global.asax, override the AddRequiredServices and paste the following code:
protected override void AddRequiredServices() { WebClientApplication.AddServiceIfMissing<WebConfigModuleInfoStoreExtended, IModuleInfoStore>(RootContainer); base.AddRequiredServices(); }
Basically, I took inspiration from Paulo Morgado’s post to figure out how to replace the calls to the HttpRequest to use HttpRuntime.
You can find the complete code implemented in one of the quickstarts for CWAB to download from here.
I hope you can find this post helpful.
Why Prism WPF applications closes when a non Shell window is closed?
October 28th, 2009
If you use Prism in your WPF applications, you will notice that the Shell window is usually the application’s main window. If you want to check it just execute in debug time Application.Current.MainWindow from the immediate window.
In the Codeplex forum we received an interesting question that said that an application was being shutdown after its Login window was closed which was instantiated from the OnStartup method.
The reason for this particular behavior is that WPF’s Window class has a property named ShutdownMode with default value OnLastWindowsClose. So if you instantiated a window before instantiating any other window and close it, WPF implicitly calls Shutdown. This is because it is the first and unique window in the application lifetime so far.
What happens if you have a similar scenario?. You can implement the two following approaches:
- Instantiate the Login window after the Shell window, because in this way the Shell will be the last window and main windows at once, so the Shutdown method doesn’t be called after closes the Login window.
- Choose to close the application explicitly. To do this, you must set the ShutdownMode with the value OnExplicitShutdown, which requires an explicit Shutdown method call to stop the application.
Demonstration
You can find in this zip file the following two applications which shows how it works:
- ClosingSolution: The application closes after closing the Login window.
- NotClosingSolution: The application closes explicitly.
Note: The code I provided doest not follow the best practices, it’s just for demo purposes.
I hope you can find this post useful.
How to change the ASP.NET Page theme programmatically in CWAB
October 3rd, 2009
One of things that we may need in a CWAB application is changing the ASP.Net page theme programmatically based on some logic.
If we want to achieve this, probably we will quickly be aware which it presents some design challenges for us:
- What is the best place to put your logic?
- How should we expose the artifact which retrieves the theme name?
- When and where must we set the theme in the ASP.Net page?
That said, I think that a good idea could be creating a global service in the Shell Module to retrieve the theme. Because in this way we will consume this service from a page to set the theme programmatically.
Inspired by this forum thread, the logic to determine that ThemeName is retrieved based on the name of site. in the sample explain below.
If your not familiar with the topics listed below, consider taking a look to the links before starting with the steps I listed.:
- Register a new service as Global Service.
- Dependency Injection to access the service from the page.
The steps to implement one of the possible solutions are the following:
Creating the ThemeResolutionProvider service
- Create a new folder named Services under the Shell Module.
- Add a new interface named IThemeProvider in the Services folder and a new class named ThemeResolutionProvier in the Services folder.
- Update the IThemeProvider.cs with the following code:
public interface IThemeProvider { string GetThemeName(); }
- Implement ThemeResolutionProvider.cs like this:
public class ThemeResolutionProvider : IThemeProvider { private IHttpContextLocatorService _httpContextLocatorService; public ThemeResolutionProvider([ServiceDependency] IHttpContextLocatorService httpContextLocatorService) { this._httpContextLocatorService = httpContextLocatorService; } public string GetThemeName() { string themeName = string.Empty; var request = this._httpContextLocatorService.GetCurrentContext().Request; switch (request.Url.Authority) { case "YourSite": { themeName = "YourCustomeTheme"; break; } default: { themeName = "Default"; break; } } return themeName; } }
Note: if you examine this code you will notice that the constructor has an argument with an attribute ServiceDependecy. This is necessary to notify ObjectBuilder to inject the object (for further information visit Dependency Injection). Also notice that the IHttpContextLocatorService helps you to access the HttpContext (to obtain the name of the site from the module).
Using the ThemeResolutionProvider service.
- Once you have created the service, you should register it as a Global Service in the ShellModuleInitializer class under the Shell project. So in this class, locate AddGlobalServices method and add the following code to the method body to register the theme service.
protected virtual void AddGlobalServices(IServiceCollection globalServices) { //more code here globalServices.AddNew<ThemeResolutionProvider, IThemeProvider>(); }
- Finally you just need to programmatically set the ThemeName in your page, by adding the following property to your page:
[ServiceDependency] public IThemeProvider ThemeResolutionProvider { set { this.Theme = value.GetThemeName(); } }
Note: Here the property has the ServiceDependency attribute, to notify ObjectBuilder that in the Page PreInit it has to inject an instance of the IThemeProvider. As the IThemeProvider is injected OnPreInit it is possible to set the theme. You can read more about that.
Important: If you have just a few pages where you have to apply this behavior, this is a good approach. But take in account that you can create a base class which inherits from Microsoft.Practices.CompositeWeb.Web.UI.Page to implement this behavior for an entire website.
I hope that this post helps you. As always your feedback is really appreciated.
How CWAB takes advantage of ObjectBuilder
September 25th, 2009
As you may know Composite Web Application Block (a.k.a. CWAB) is part of a compendium of application blocks which are included into Web Client Software Factory (a.k.a. WCSF).
CWAB helps architects and developers create web applications obtaining the following benefits:
- Separation of Concerns
- Modularity
- Extensibility
- Testability
- Maintainability
When I started researching WCSF, one of the most interesting things I noticed was how CWAB takes advantage of ObjectBuilder and I want to share with you some highlights about it.
ObjectBuilder Introduction
ObjectBuilder is a framework for creating dependency injection systems that uses the factory pattern to create object instances. So, basically it creates and injects instances of objects of the appropriate type into the application at run time.
That is why, when you inspect the source code for a CWAB application, you will notice that the application does not always create instances of another component by directly constructing an object (using new). Instead, the source code contains attributes such as CreateNew and ServiceDependency which are in charge of supporting the injection of objects at run time.
ObjectBuilder with CWAB
One might wonder, how does ObjectBuilder work when a property has the CreateNew attribute in a CWAB page?
By default in a CWAB application, its pages inherit from Microsoft.Practices.CompositeWeb.Web.UI.Page which overloads the OnPreInit method where calls to ObjectBuilder are made in order to iterate through the page properties which contain a CreateNew attribute and allow the creation of all needed instances for the page.
To show this more clearly you can find below a piece of code.
public partial class MyPage : Microsoft.Practices.CompositeWeb.Web.UI.Page, IContactsListView { [CreateNew] public MyPagePresenter Presenter { set { this._presenter = value; if (value != null) { this._presenter.View = this; } } get { return this._presenter; } } // more code here } |
So far, we’ve explained how ObjectBuilder and a CWAB page work together, but how does ObjectBuilder work with a CWAB Presenter or Controller from a module?
In some cases in order to decouple your components in a CWAB Module, you might use interfaces unlike CWAB Page which uses concrete types, so the CWAB Module has to find the way to notify ObjectBuilder how to determine the type of object that it creates.
To do this, CWAB exposes a container where developers can indicate how to match interfaces with concrete object types in the “Initializer Module”.
public class ContactsModuleInitializer : ModuleInitializer { public override void Load(CompositionContainer container) { base.Load(container); AddGlobalServices(container.Parent.Services); AddModuleServices(container.Services); RegisterSiteMapInformation(container.Services.Get<ISiteMapBuilderService>(true)); container.RegisterTypeMapping<IMyPageController, MyPageController>(); } //more code here } |
Once the developer adds the mappings between interfaces and concrete types, they will be able to use interfaces inside CWAB Modules.
public class MyPageViewPresenter : Presenter<IMyPageView> { private IMyPageController _controller; public DefaultViewPresenter([CreateNew] IMyPageController controller) { this._controller = controller; } //more code here } public class MyPageController { private IService _service; public MyPageController ([ServiceDependency] IService service) { _service = service; } //more code here } |
If you want continue reading more about it, I recommend to visit the following blog post How To: about Extend Object Creation in the Web Client Software Factory
I hope the article helps you to understand more about ObjectBuilder with CWAB. As always your feedback is really appreciated.
