Windows 7 & .NET 4.0 Beta 1

Standard

I upgraded to Windows 7 today and failed to Uninstall .NET 4.0 and VS2010 BETA 1. This left me with non working SQL Management Studio (2005 & 2008) with the error “Microsoft SQL Management Studio Package failed to load”

It also screwed up all my Red Gate software and VS2010. Then I found out you should install Windows 7 after removing .NET 4.0 BETA 1 and Visual Studio other wise you will have to flatten your PC and do a fresh install as the .NET Framework is broken and unfixable. Not really true. I found this worked for me.

Remove .NET 4.0 BETA 1

For x86 OS:

cmd /c "msiexec /x {19BD09BF-3BBD-3663-A5ED-50B6B2B07E42} /qb"
cmd /c "msiexec /x {1DF6A8F6-5048-323F-8758-DA533CE0F07E} /qb"

For x64 OS:

cmd /c "msiexec /x {175D5555-EE49-3033-99AF-BC1E206223FD} /qb"
cmd /c "msiexec /x {13B27C82-19BA-3494-9420-F932B40673CA} /qb"

Then

  • Reboot
  • Uninstall Visual Studio 2010 and its redistributables
  • Reboot
  • Install .NET 4.0
  • Reboot
  • Install Visual 2010

Links to this :-

Download .NET 4.0 Beta 1
MSDN Forums where I found above info.
Hanselman – Before Upgrading To Windows 7

Now I can wait until I get an SSD drive before I do a clean install :-).

Don’t buy Norton 360

Standard

I don’t normally rant on this blog, but don’t buy this product it’s rubbish. It slows down you pc to a crawl, takes up loads of resources, crashes trying to backup your data. Last time I ever spend money on Symantec software.

p.s. Can’t even attempt to get a refund.

Update

I have just uninstalled it and quite shocked how much quicker my computer is……

ActionImage – ASP.NET MVC

Standard

I was in the middle of doing some grid work using the MVC Contrib UI Grid and need an image column. It was a bit messy and a struggle. Turns out there is not a ActionImage helper that behaves like ActionLink. There are plenty of quick hacks about but I wanted some that behaves the same as ActionLink with the same overloads and some extra bits.

It supports all the normal overloads that ActionLink provides in System.Web.Mvc.Html and the generic versions from Microsoft.Web.Mvc.Html. It also support html attributes for both the anchor tag and the image tag.

Also one thing the Generic version of ActionLink does not have is the ability to specify additional route values as well as the action parameters. ActionImage supports the merging of the action parameters and additional route values.

Any suggestions, improvements, fixes, are always welcome.

Regards Tobi.

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.Web.Mvc.Internal;

namespace GMS.Web.Mvc.Html
{
    public static class HtmlHelpers
    {

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, new RouteValueDictionary(), new RouteValueDictionary());
        }

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, object routeValues)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary());
        }

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, controllerName, new RouteValueDictionary(), new RouteValueDictionary());
        }

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, RouteValueDictionary routeValues)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, routeValues, new RouteValueDictionary());
        }

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, object routeValues, object htmlanchorAttributes)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlanchorAttributes), null);
        }

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, RouteValueDictionary routeValues, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, null, routeValues, htmlanchorAttributes, htmlImageAttributes);
        }

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName, object routeValues, object htmlanchorAttributes)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, controllerName, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlanchorAttributes), null);
        }

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, object routeValues, object htmlanchorAttributes, object htmlImageAttributes)
        {
            return htmlHelper.ActionImage(imageUrl, linkText, actionName, controllerName, protocol, hostName, fragment, new RouteValueDictionary(routeValues), new RouteValueDictionary(htmlanchorAttributes), new RouteValueDictionary(htmlImageAttributes));
        }

        public static string ActionImage<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> action, string imageUrl, string linkText) where TController : Controller
        {
            return htmlHelper.ActionImage(action, imageUrl, linkText, null, null, null);
        }

        public static string ActionImage<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> action, string imageUrl, string linkText, object routeValues) where TController : Controller
        {
            return htmlHelper.ActionImage(action, imageUrl, linkText, routeValues, null, null);
        }

        public static string ActionImage<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> action, string imageUrl, string linkText, object routeValues, object htmlanchorAttributes, object htmlImageAttributes) where TController : Controller
        {
            return htmlHelper.ActionImage(action, imageUrl, linkText, routeValues, new RouteValueDictionary(htmlanchorAttributes), new RouteValueDictionary(htmlImageAttributes));
        }

        public static string ActionImage<TController>(this HtmlHelper htmlHelper, Expression<Action<TController>> action, string imageUrl, string linkText, object routeValues, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes) where TController : Controller
        {

            var _routeValuesFromExpression = ExpressionHelper.GetRouteValuesFromExpression(action);
            var _mergedRouteValues = MergeRouteValueDictionaries(_routeValuesFromExpression, new RouteValueDictionary(routeValues));

            // get the action name
            //
            var _actionName = ((MethodCallExpression)action.Body).Method.Name;

            // get the bare url for the Action using the current
            // request context
            //     
            var _url = new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(_actionName, _mergedRouteValues);

            return GetImageLink(_url, linkText, imageUrl, htmlanchorAttributes, htmlImageAttributes);

        }

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName, RouteValueDictionary routeValues, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes)
        {
            // get the bare url for the Action using the current
            // request context
            //
            var _url = new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(actionName, controllerName, routeValues);

            return GetImageLink(_url, linkText, imageUrl, htmlanchorAttributes, htmlImageAttributes);

        }

        public static string ActionImage(this HtmlHelper htmlHelper, string imageUrl, string linkText, string actionName, string controllerName, string protocol, string hostName, string fragment, RouteValueDictionary routeValues, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes)
        {

            // get the bare url for the Action using the current
            // request context
            //
            var _url = new UrlHelper(htmlHelper.ViewContext.RequestContext).Action(actionName, controllerName, routeValues, protocol, hostName);

            return GetImageLink(_url, linkText, imageUrl, htmlanchorAttributes, htmlImageAttributes);

        }

        /// <summary>
        /// Build up the anchor and image tag.
        /// </summary>
        /// <param name="url">The URL.</param>
        /// <param name="linkText">The link text.</param>
        /// <param name="imageUrl">The image URL.</param>
        /// <param name="htmlanchorAttributes">The HTML anchor attributes.</param>
        /// <param name="htmlImageAttributes">The HTML image attributes.</param>
        /// <returns></returns>
        internal static string GetImageLink(string url, string linkText, string imageUrl, IDictionary<string, object> htmlanchorAttributes, IDictionary<string, object> htmlImageAttributes)
        {
            // build up the image link.
            // <a href="ActionUrl"><img src="ImageUrl" alt="Your Link Text" /></a>
            //

            var _linkText = !string.IsNullOrEmpty(linkText) ? HttpUtility.HtmlEncode(linkText) : string.Empty;

            // build the img tag
            //
            TagBuilder _image = new TagBuilder("img");
            _image.MergeAttributes(htmlImageAttributes);
            _image.MergeAttribute("src", imageUrl);
            _image.MergeAttribute("alt", _linkText);

            // build the anchor tag
            //
            TagBuilder _link = new TagBuilder("a");
            _link.MergeAttributes(htmlanchorAttributes);
            _link.MergeAttribute("href", url);

            // place the img tag inside the anchor tag.
            //
            _link.InnerHtml = _image.ToString(TagRenderMode.Normal);

            // render the image link.
            //
            return _link.ToString(TagRenderMode.Normal);

        }


        /// <summary>
        /// Merges the 2 source route value dictionaries.
        /// </summary>
        /// <param name="routeValueDictionary1">RouteValueDictionary 1.</param>
        /// <param name="routeValueDictionary2">RouteValueDictionary 2.</param>
        /// <returns></returns>
        internal static RouteValueDictionary MergeRouteValueDictionaries(RouteValueDictionary routeValueDictionary1, RouteValueDictionary routeValueDictionary2)
        {
            var _mergedRouteValues = new RouteValueDictionary();

            if ((routeValueDictionary1 != null) & (routeValueDictionary2 != null))
            {
                foreach (KeyValuePair<string, object> routeElement in routeValueDictionary1)
                {
                    _mergedRouteValues[routeElement.Key] = routeElement.Value;
                }

                foreach (KeyValuePair<string, object> routeElement in routeValueDictionary2)
                {
                    _mergedRouteValues[routeElement.Key] = routeElement.Value;
                }

                return _mergedRouteValues;
            }

            return null;
        }

    }

}

Kill all database connections

Standard

Just came across this script – very useful

--------------------------------------------------------------------------------------
/*** CREATED BY AJITH DHARWAR                                                     ***/
/*** This procedure will accept a DB name and drop all connections to the DB.    ***/
--------------------------------------------------------------------------------------
CREATE PROCEDURE usp_killDBConnections
    @DBName VARCHAR(50),
    @withmsg BIT = 1
AS 
    SET NOCOUNT ON
    DECLARE @spidstr VARCHAR(8000)
    DECLARE @ConnKilled SMALLINT
    SET @ConnKilled = 0
    SET @spidstr = ''

    IF DB_ID(@DBName) > 4 
        BEGIN
            PRINT 'Connections to system databases cannot be killed'
            RETURN
        END

    SELECT  @spidstr = COALESCE(@spidstr, ',') + 'kill ' + CONVERT(VARCHAR, spid) + '; '
    FROM    master..sysprocesses
    WHERE   dbid = DB_ID(@DBName)

    IF LEN(@spidstr) > 0 
        BEGIN
            EXEC ( @spidstr
                )

            SELECT  @ConnKilled = COUNT(1)
            FROM    master..sysprocesses
            WHERE   dbid = DB_ID(@DBName) 

        END

    IF @withmsg = 1 
        PRINT CONVERT(VARCHAR(10), @ConnKilled) + ' Connection(s) killed for DB ' + @DBName
GO

You can then use it like this

EXEC sp_msforeachdb 'EXEC usp_killDBConnections @DBName=''?'''

Or like this

EXEC usp_killDBConnections @DBName='MyDatabase'

SQL Report Server & ASP.MVC

Standard

I have used MS SQL Report server a lot and one of the most common scenarios is to render a report and have it download a PDF / Excel etc. I have not seen many posts regarding how to do this end-to-end using MVC. So I thought I share my method.

The demo project will be split into 3 parts.

  1. The Report Server Execution Service.
    2. The Report Server Repository Layer.
    3. The Report Server Service Layer.
    4. The User Interface.
    You’ll need
  1. Visual Studio 2008
  2. ASP.MVC RTM
  3. SQL Server 2005/2008

You’ll also have installed and working the MSSQL Report Server and a test report.Create a New Blank Solution SQL Server Report Solution

imageAnd then add 2 Class Libraries and a MVC Web Site – You can choose whether or not to add the MVC Test projects.

  • Demos.SqlReports.Data
  • Demos.SqlReports.Services
  • Demos.SqlReports.Web

I’ll also add a test project for the Data and Service Layer, I’m just using the default unit test framework that comes with VS 2008. You can of course use something else (nUnit, xUnit etc).

  • Demos.SqlReports.Tests
    You should have something like this now.

image 

We need to add a Web Reference to the Report Server at the data layer. My Report Server Execution Service URL is

http://localhost/ReportServer$SQLSERVER_001/ReportExecution2005.asmx

Yours may differ so check it in IIS.

Also, I’m adding a web reference – not a service reference. You can do this though the add service reference dialog box by clicking Advanced | Add Web Reference.

image

I always postfix Proxy on the end of the Web Reference Name for clarity.

Once added rename Class 1  to ReportServerRepository.cs and also create an Interface Class IReportsRepository.cs

Move these files into a sub folder Data so they are organised.

image

Let’s add some code.

using System;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Web.Services.Protocols;
using Demos.SqlReports.Data.ReportExecution2005Proxy;

namespace Demos.SqlReports.Data
{

    ///
    /// Contains the response data from a RenderReport request
    /// to the report server.
    ///
    public sealed class RenderReportResponse
    {
        public byte[] ReportData { get; set; }
        public ExecutionInfo ExecutionInfo { get; set; }
        public ReportExecution2005Proxy.Warning[] Warnings { get; set; }
        public string SessionId { get; set; }
        public string ContentType { get; set; }
        public string HistoryID { get; set; }
        public string DevInfo { get; set; }
        public string Encoding { get; set; }
        public string MimeType { get; set; }
        public string Extension { get; set; }
        public string[] StreamIds { get; set; }
    }

    ///
    /// Report Server Repository
    ///
    public sealed class ReportServerRepository : IReportsRepository
    {

        #region Constructors

        ///
        /// Initializes a new instance of the  class.
        ///
        public ReportServerRepository()
        {
            this.Initialise();
        }

        #endregion

        #region Declarations

        private NetworkCredential netCredential;
        private ReportExecutionService webServiceProxy;

        #endregion

        #region Private Members

        ///
        /// Initialises this instance and set the credentials for
        /// the report server.
        ///
        private void Initialise()
        {

            webServiceProxy = new ReportExecutionService();
            netCredential = new NetworkCredential("MyUserName", "MyPassword");
            Uri uri = new Uri(webServiceProxy.Url);
            ICredentials credentials = netCredential.GetCredential(uri, "Basic");
            webServiceProxy.Credentials = credentials;
            webServiceProxy.PreAuthenticate = true;

        }

        ///
        /// Gets the type of the content.
        ///
        ///
The file extension.
        ///
        private static string GetContentType(string fileExtension)
        {
            switch (fileExtension.ToLower())
            {
                case ".pdf": return "application/pdf";
                case ".tif": return "image/tiff";
                case ".xls": return "application/ms-excel";
                case ".xml": return "text/xml";
                default: return "text/plain";
            }

        }

        ///
        /// Renders the report.
        ///
        ///
The parameters.
        ///
The report path.
        ///
The format.
        ///
        private static RenderReportResponse RenderReport(ReportExecution2005Proxy.ParameterValue[] parameters, string reportPath, string format)
        {

            using (var rs = new ReportExecutionService())
            {

                try
                {

                    rs.Credentials = CredentialCache.DefaultCredentials;

                    // Render arguments
                    //
                    const string _historyID = null;
                    const string _devInfo = @"False";
                    string _encoding;
                    string _mimeType;
                    string _extension;
                    ReportExecution2005Proxy.Warning[] _warnings;
                    string[] _streamIDs;

                    ExecutionInfo _execInfo = new ExecutionInfo();
                    ExecutionHeader execHeader = new ExecutionHeader();

                    rs.ExecutionHeaderValue = execHeader;
                    _execInfo = rs.LoadReport(reportPath, _historyID);

                    rs.SetExecutionParameters(parameters, "en-us");
                    String SessionId = rs.ExecutionHeaderValue.ExecutionID;

                    var _reportData = rs.Render(format, _devInfo, out _extension, out _encoding, out _mimeType, out _warnings, out _streamIDs);

                    var _response = new RenderReportResponse
                                        {
                                            ReportData = _reportData,
                                            ExecutionInfo = _execInfo,
                                            Warnings = _warnings,
                                            SessionId = SessionId,
                                            ContentType = GetContentType(format),
                                            HistoryID = _historyID,
                                            DevInfo = _devInfo,
                                            Encoding = _encoding,
                                            MimeType = _mimeType,
                                            Extension = _extension,
                                            StreamIds = _streamIDs
                                        };
                    return _response;

                }
                catch (SoapException e)
                {

                    // handle exception
                    //
                    throw new ApplicationException(
                        string.Format("Error occurred rendering the report : {0}", reportPath), e);

                }

            }

        }

        #endregion

        #region IReportServerRepository Members

        ///
        /// Renders the Demo Report.
        ///
        ///
The reportParameter.
        ///
        public RenderReportResponse RenderDemoReport(string reportParameter)
        {

            var _params = new[] { new ReportExecution2005Proxy.ParameterValue { Name = "p_ReportParameter", Value = reportParameter } };

            return RenderReport(_params, "My Demo Report", "PDF");
        }

        #endregion

    }

}

And add some to the interface class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Demos.SqlReports.Data
{
    interface IReportsRepository
    {

        ///
        /// Renders the Demo Report.
        ///
        ///
The reportParameter.
        ///
        RenderReportResponse RenderDemoReport(string reportParameter);

    }
}

The reason for returning a class of RenderReportResponse back is that we can have the whole response delivered to the UI and make use of it if required.

Ok let’s add some code to the service class.

Rename Class 1  to ReportService.cs and also create an Interface Class IReportService.cs

The purpose of the interfaces and the service class is to abstract away the implementation of the repository and to decouple as much as possible.

The UI should only ever call the service class. You can then swap out repositories easily when testing code or using an alternative repository. It also lends its self well to a plug-in architecture or if you plan to implement IoC / Dependency Injection later on.

Code for the Service Class

(make sure you have added a project reference for Demos.SqlReports.Data)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demos.SqlReports.Data;

namespace Demos.SqlReports.Services
{
    public partial class ReportService : IReportService
    {

        readonly IReportsRepository _repository;

        ///
        /// Creates a ReportService based on the passed-in repository
        ///
        ///
An IReportsRepository
        public ReportService(IReportsRepository repository)
        {
            _repository = repository;

            if (_repository == null)
                throw new InvalidOperationException("Repository cannot be null");

        }

        ///
        /// Creates a ReportService based on the default repository
        ///
        public ReportService()
        {
            _repository = new ReportServerRepository();
        }

        #region IReportService Members

        public RenderReportResponse RenderDemoReport(string reportParameter)
        {
            return _repository.RenderDemoReport(reportParameter);
        }

        #endregion
    }
}

 

Code for the Service Interface Class

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Demos.SqlReports.Data;

namespace Demos.SqlReports.Services
{
    public interface IReportService
    {

        ///
        /// Renders the Demo Report.
        ///
        ///
The reportParameter.
        ///
        RenderReportResponse RenderDemoReport(string reportParameter);

    }

}

 

Move these files into a sub directory i.e. Reports. Build the project make sure there are no errors.

 

Implementing the UI

 

In the MVC Project we are going to use the default HomeController for our demo. Add a project reference for the Data and Service Layers.

The first thing we need to do is create a class for the ActionResultHelper.cs. Add the class file in a subdirectory Helpers (keep the class namespace flat i.e. Demos.SqlReports.Web remove any namespace additions if you create the sub directory first.

Add the code.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Demos.SqlReports.Services;
using Demos.SqlReports.Data;

namespace Demos.SqlReports.Web
{
    public class ReportServerResult : ActionResult
    {
        public RenderReportResponse ReportData { get; set; }
        public string FileName { get; set; }

        public override void ExecuteResult(ControllerContext context)
        {

            context.HttpContext.Response.Clear();
            context.HttpContext.Response.ClearHeaders();
            context.HttpContext.Response.ContentType = ReportData.ContentType;
            context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename="" + FileName + """);
            context.HttpContext.Response.BinaryWrite(ReportData.ReportData);
            context.HttpContext.Response.Flush();

        }
    }
}

Let me explain a little what's going on here. By inheriting the ActionResult base class we can pass the report servers response directly to the response stream of the Controller Action. This is a neat way because it also allows you to Unit Test the response and you can reuse it anywhere you render a report.

Let’s create an Action in Home Controller.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Demos.SqlReports.Services;
using Demos.SqlReports.Data;

namespace Demos.SqlReports.Web.Controllers
{
    [HandleError]
    public class HomeController : Controller
    {

        private readonly IReportService _reportService;

        public HomeController()
        {
            _reportService = new ReportService(new ReportServerRepository());
        }

        public ActionResult Index()
        {
            ViewData["Message"] = "Welcome to ASP.NET MVC!";

            return View();
        }

        public ActionResult About()
        {
            return View();
        }

        ///
        /// Gets the demo report.
        ///
        ///
The report parameter.
        ///
        public ActionResult GetDemoReport(string reportparameter)
        {
            // call the report service and render the report
            //

            var _response = _reportService.RenderDemoReport(reportparameter);

            // returnn the result using a custom action result class.
            //
            return new ReportServerResult { FileName = "Demo Report.pdf", ReportData = _response };

        }

    }
}

As you can see the code is nice and concise. The Response Data from service layer is passed straight into the ReportServerResult  which outputs the report to the response stream.

Add an ActionLink to the Index.aspx file

< %@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>

    Home Page

< %= Html.Encode(ViewData["Message"]) %>

To learn more about ASP.NET MVC visit http://asp.net/mvc. < %= Html.ActionLink("Render Report","GetDemoReport", "HomeController",new{ reportparameter = "ParameterValue"}) %>

 

That’s it. normally I’d build the unit tests before jumping into the code but this isn’t a session on TDD. I’ll leave that bit to you. Next I’d like to get the Report Viewer control working with ASP.MVC. You can download the test solution here.

Download Solution - SQL Server Report Solution.zip

MVC – Strongly Typed Global ViewData

Standard

Most MVC stuff I have been doing has been quite basic and the knowledge gleaned off many blog sites ( thanks to you all :-) )I’m not a prolific blogger – too busy!!!, I’ll only blog when I have something to useful to share that isn’t easy to find.

I was looking for a way to provide ViewData at the Model level so that I could have some parameters available after every action that were strongly typed and injected into the ActionResult instead of ViewData["MyData"]. I want to use Model.MyData

I had a good search about but nothing definitive so I cam up with this.

The Base Controller Class.

It’s always a good idea to have you own base controller that is inherited from your other controllers. Here we are using it for storing Global Settings/Properties or any helper methods etc.

using System;
using System.Web.Mvc;

namespace GlobalViewData.Controllers
{

    /// 
    /// Base data container for ViewData Models
    /// 
    public abstract class BaseFormViewModel
    {
        public string MyData { get; set; }
    }

    /// 
    /// Base controller that all controllers inherit from.
    /// 
    public abstract class BaseController : Controller
    {

        /// 
        /// Initializes a new instance of the  class.
        /// 
        protected BaseController()
        {
            MyData = "I have set this in the BaseController";
        }

        public string MyData { get; set; }

        /// 
        /// Method called after the action method is invoked.
        /// 
        /// Contains information about the current request and action.
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            // check there is data in the Model
            //
            if (filterContext.Controller.ViewData.Model != null)
            {
                // bit of reflection magic and get the types
                //
                Type _baseFormViewModelType = typeof(BaseFormViewModel);
                Type _modelType = filterContext.Controller.ViewData.Model.GetType();

                // if the model type is derived from the base type then
                // we can set some properties.
                //

                if (_baseFormViewModelType.IsAssignableFrom(_modelType))
                {
                    // inject the value to the ViewData.Model property
                    //
                    _modelType.GetProperty("MyData").SetValue(filterContext.Controller.ViewData.Model, MyData, null);
                }
            }

            base.OnActionExecuted(filterContext);

        }       
    }
}

The Home Controller Class

This inherits from the BaseController and also has a Data Class called HomeFormViewModel which inherits from BaseFormViewModel.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace GlobalViewData.Controllers
{

    public class HomeFormViewModel : BaseFormViewModel
    {
        public string LocalData { get; set; }
    }

    [HandleError]
    public class HomeController : BaseController
    {
        public ActionResult Index()
        {
            ViewData["Message"] = "Welcome to ASP.NET MVC!";

            return View();
        }

        public ActionResult About()
        {
            var _formData = new HomeFormViewModel {LocalData = "I have set this in the Home Controller"};

            return View(_formData);
        }
    }
}

 

When the About Action is called the  HomeFormViewModel  is populated and then caught by the BaseController OnActionExecuted method which injects the required data into the HomeFormViewModel which is derived from BaseFormViewModel

In About.aspx

< %@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>



    About Us


    

About

Global - From BaseController

Local - From HomeController

As you can see from the image below the data is populated.

image

Hope this is useful!

Adventures in MVC.NET

Standard

I have been watching the progress of the new MVC framework for Micrsoft.NET and must say I can’t wait to start using it. However like all things new I have been waiting for some proper guidance and for the software to get to release status – which should not be far off (a month or so). Scott Guthrie has been making some excellent post regarding the progress and features of MVC – http://weblogs.asp.net/scottgu/archive/tags/MVC/default.aspx

I have also being following Rob Conerly series on MVC Storefront http://blog.wekeroad.com/mvc-storefront which is providing some excellent learing both in TDD and DDD practices apart from the MVC framework, I suggest anyone looking at .NET development with or without the MVC part check out and watch the series, you’ll learn at lot. The series up to EP 23 is published here - http://www.asp.net/learn/mvc-videos the rest can be found on Rob’s blog.

I have a real work app to write and I’d like to use MVC so when I start using it I’ll blog a bit more about it.

Regards

Tobi.