Apr 29, 2010

Loading common model into view

In our view, there are some data which are require across all page, such as site bar data, menu, and so on. We can split them into partial view and using Html.RenderAction. But this should not be overused, because of performance issue and also it kind of violate separation of concerns. In this case, the view is controlling data. If we want to use Html.RenderPartial, data can be explictly passed in Parent View, or we can inject the data into ViewData in the stack before ActionResult is returned from controller. For example, we can use base controller, and override

public void BaseController : Controller
{
    protected override OnActionExecuting(ActionExecutingContext context)
    {
        ViewData.Add(your_data);
    }
}

Another option is use ActionFilterAttribute. It is designed to solve cross-cutting concerns, like authorization, logging and so on. But we can use it to load common data as well.


public class RequireCommonDataAttribute : ActionFilterAttribute
{
   public override void OnActionExecuting(ActionExecutionContext filterContext)
   {
        filterContext.Controller.ViewData.Add(your_data);

   }
}

public class MyController
{
   [RequireCommonDataAtrribute]
   public ActionResult View()
   {
    }
}

Apr 14, 2010

How to use bookmark in WF4

BookMark can be used to implement event driven style workflow. Below is some sample code.

//in your activity, you override Execute method, to put your workflow idle
protected override void Execute(NativeActivityContext context)
{
    string bookmark = this.BookmarkName.Get(context);
    context.CreateBookmark(bookmark,
                           delegate(NativeActivityContext ctx, Bookmark bMark, object state)
                           {
                               string input = state as string;
                               ctx.SetValue(this.Result, input);
                           });
}

//in your host, wakeup your workflow
application.ResumeBookmark(bookmarkName, text);

Loading string as workflow

Here is some sample code that loads string as workflow

Stream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(stringXaml));
Activity wf = ActivityXamlServices.Load(stream);
IDictionary results = WorkflowInvoker.Invoke(wf);              

WF4 hosting option

  • WorkflowInvoker

    Simple "method call" style of workflow execution for short-lived worklfow (persistence is not allowed)

  • WorkflowApplication

    Single host with asynchronousexecution, support persistence, provides a set of instance operation and notifications of instance life cycle events.

  • WorkflowServiceHost

    Multi-instance host for WF4 workflow services and also for workflows that are not services, support persistence, expose endpoints for instance operations, support configuration, windows server AppFabric provides IIS/WAS deployment, configuration, management, and monitoring support.

  • WorkflowInstance

    Abstract base class for creating custom hosts, provide access to lowest level of hosting capabilities.

Apr 1, 2010

Debugging T4

1. add "template debug="true""
2. cd %temp%, and find the latest generated cs file
3. Add System.Diagnostics.Debugger.Break() in you template file, below is example of simple template.
namespace Microsoft.VisualStudio.TextTemplating28A7CF507D33073FC06B43678F225DE4
{
    using System;
    
    
    #line 1 "C:\other_projects\Vs.netCustomization\T4Demo\Template1.t4"
    public class GeneratedTextTransformation : Microsoft.VisualStudio.TextTemplating.TextTransformation
    {
        public override string TransformText()
        {
            try
            {
                
                #line 3 "C:\other_projects\Vs.netCustomization\T4Demo\Template1.t4"
 
System.Diagnostics.Debugger.Break();

this.WriteLine("hello");


                
                #line default
                #line hidden
            }
            catch (System.Exception e)
            {
                e.Data["TextTemplatingProgress"] = this.GenerationEnvironment.ToString();
                throw;
            }
            return this.GenerationEnvironment.ToString();
        }
    }
    
    #line default
    #line hidden
}

The based class's dll in in C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualStudio.TextTemplating.10.0\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.TextTemplating.10.0.dll, Microsoft.VisualStudio.TextTemplating.10.0, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a he text template transformation process has two steps. In the first step, the text template transformation engine creates a class that is referred to as the generated transformation class. In the second step, the engine compiles and executes the generated transformation class, to produce the generated text output. The generated transformation class inherits from TextTransformation. Any class specified in an inherits directive in a text template must itself inherit from TextTransformation. TransformText is the only abstract member of this class.

vs.net template

User' template location C:\Documents and Settings\[user_name]\My Documents\Visual Studio 2010\Templates\ItemTemplates C:\Documents and Settings\[user_name]\My Documents\Visual Studio 2010\Templates\ProjectTemplates Global template C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\ProjectTemplates

When you manually pack your template files into zip file, do not put them into a folder and zip the folder, you should zip the files directly (not under a folder). More information can be found http://msdn.microsoft.com/en-us/library/6db0hwky%28v=VS.80%29.aspx