Welcome to MSDN Blogs Sign in | Join | Help

My First Silverlight Behavior

Blend/Silverlight 3 introduces a new powerful feature – Behaviors.

Behaviors allow designers to take advantage of new levels of interactivity declaratively, without writing code.

In short, a behavior is a reusable piece that encapsulates some functionality that can be attached to an object to extend its built-in interactivity capabilities.

For instance, a behavior can be attached to a TextBox to give it auto-complete functionality; or a behavior can be attached to a Canvas to make it reflect its content.

“Behaviors are a great new element of the designer-developer workflow: For developers, they provide a well-supported design pattern that makes it possible to encapsulate interactivity well separated from actual UI instances. For a designer, behaviors are building blocks that make interactivity possible beyond the boundaries and limitations of classical custom controls.”

Blend 3 Behaviors: Interactivity Without Code

 

You can find on the web great material about behaviors:

- What they are: Product Feature Highlight: Expression Blend 3 – Behaviors; An Introduction to Behaviors, Triggers, and Actions

- How to write them: Silverlight Behaviors

- Where to find them: Expression Gallery - Behaviors

 

What I’d like to show you is my experience writing my first Silverlight behavior.

I didn’t spend much time reasoning about what behavior I would like to implement: “The popular Reflection effect, of course!”, I thought.

In Silverlight 2 the classic way of implementing reflection is achieved by doubling the XAML we want to reflect, applying a ScaleTransform to flip the copied XAML vertically, and applying an OpacityMask to fade out the copy.

In Silverlight 3 we don’t have yet a way of getting an object XAML programmatically, making it hard to double the object to reflect, but for this scenario we don’t need it anymore - we can use a VisualBrush to render an existing visual into a brush, like in WPF.

How to: Create a Reflection

These blog entries describe the same technique:

More on Silverlight 3's Writeable Bitmap

Discovering Silverlight 3 – Poor Man’s Visualbrush Behavior

 

Now that we know how to substitute the flipped duplicated XAML by an image we have all we need - let’s start then.

 

- Create a new Silverlight Class Library and reference Microsoft.Expression.Interactivity

(C:\Program Files\Microsoft Expression\Blend 3 Preview\Libraries\Silverlight\Microsoft.Expression.Interactivity.dll)

 

- Declare the behavior class and make it “attachable” to a Canvas.

public class ReflectionBehavior : Behavior<Canvas>

 

- Nothing to do on the constructor.

public ReflectionBehavior()

{

}

 

- Do the Wire Up  (the real “magic” happens where).

We’re adding a handler to the Canvas (associated object) Loaded Event.

protected override void OnAttached()

{

   base.OnAttached();

   this.AssociatedObject.Loaded += new RoutedEventHandler(sourceObject_Loaded);

}

protected override void OnDetaching()

{

   base.OnDetaching();

}

 

- To make things a little more interesting we’re adding two properties to our behavior.

These dependency properties will allow us to define declaratively the beginning and end opacity of the reflection.

public static readonly DependencyProperty OpacityFromProperty =

   DependencyProperty.Register("OpacityFrom", typeof(double), typeof(ReflectionBehavior), new PropertyMetadata(0.5));

public double OpacityFrom

{

   get { return (double)GetValue(OpacityFromProperty); }

   set { SetValue(OpacityFromProperty, value); }

}

public static readonly DependencyProperty OpacityToProperty =

   DependencyProperty.Register("OpacityTo", typeof(double),  typeof(ReflectionBehavior), new PropertyMetadata(0.0));

public double OpacityTo

{

   get { return (double)GetValue(OpacityToProperty); }

   set { SetValue(OpacityToProperty, value); }

}

 

- Finally, implement the handler - this is where the real work gets done.

private void sourceObject_Loaded(object sender, System.Windows.RoutedEventArgs e)

{

 

- Let’s go slowly here…

Get the object (Panel/Canvas) to be reflected and create an Image to render the reflection.

   Panel originalCanvas = sender as Panel;

   Image reflectedImage = new Image();

 

Create a WriteableBitmap to render the visual brush (don’t forget to adjust it’s position) and set it as the reflected image source.

   System.Windows.Media.Imaging.WriteableBitmap bitmap =

      new System.Windows.Media.Imaging.WriteableBitmap((int)originalCanvas.Width, (int)originalCanvas.Height, PixelFormats.Bgr32);

   TranslateTransform correctionTransform = new TranslateTransform();

   correctionTransform.X = -originalCanvas.Margin.Left - (double)originalCanvas.GetValue(Canvas.LeftProperty);

   correctionTransform.Y = -originalCanvas.Margin.Top - (double)originalCanvas.GetValue(Canvas.TopProperty);

   bitmap.Render(originalCanvas, correctionTransform);

   reflectedImage.Source = bitmap;

 

Flip the image vertically and position it bellow the canvas.

   ScaleTransform transform1 = new ScaleTransform();

   transform1.ScaleX = 1.0;

   transform1.ScaleY = -1.0;

   TranslateTransform transform2 = new TranslateTransform();

   transform2.Y = originalCanvas.Height * 2;

   TransformGroup transformG = new TransformGroup();

   transformG.Children.Add(transform1);

   transformG.Children.Add(transform2);

   reflectedImage.RenderTransform = transformG;

 

Construct the Opacity Mask using the behavior gradient opacity properties.

   LinearGradientBrush brush = new LinearGradientBrush();

   GradientStop grad1 = new GradientStop();

   grad1.Color = Color.FromArgb((byte)(OpacityTo * 255), 0, 0, 0);

   grad1.Offset = 0.0;

   GradientStop grad2 = new GradientStop();

   grad2.Color = Color.FromArgb((byte)(OpacityFrom * 255), 0, 0, 0);

   grad2.Offset = 1.0;

   brush.StartPoint = new Point(0.5, 0);

   brush.EndPoint = new Point(0.5, 1);

   brush.GradientStops.Add(grad1);

   brush.GradientStops.Add(grad2);

   reflectedImage.OpacityMask = brush;

 

Finally, insert the image on Canvas. This way, if the canvas moves or other transform is applied to it the inner reflection image gets it too.

   originalCanvas.Children.Add(reflectedImage);

}

 

- All is set now!

Any user control can use our behavior by referencing it…

xmlns:i="clr-namespace:Microsoft.Expression.Interactivity;assembly=Microsoft.Expression.Interactivity"

xmlns:mybehavior="clr-namespace:MyBehavior;assembly=MyBehavior"

 

And applying it to a canvas, declaratively …

<Canvas x:Name="MyObject" Width="180" Height="140"  Canvas.Left="50" Canvas.Top="50" Background="White">

   <i:Interaction.Behaviors>

       <mybehavior:ReflectionBehavior OpacityFrom="0.75" OpacityTo="0" />

   </i:Interaction.Behaviors>  

   <Rectangle Width="180" Height="140" Fill="Black" RadiusX="6" RadiusY="6" />

   <Image Source="samplepic.png" Width="160" Height="120" Margin="10" />

   <TextBlock Margin="15" Text="Reflection Demo" Foreground="White" />

</Canvas>

 

Getting:

Enjoy.

Pedro Fortes

Posted by ptadcs | 0 Comments
Filed under:

The marvellous SPList.RenderAsHtml

One of these days a customer asked me if there was an easy way to build a Web Part that would be able to switch between the list views, and also wanted it to look and feel like a view of any list in Sharepoint. The first thing that crossed my mind was “huummm, that will not be easy…”, specially the look and feel part, also my skills in design… let’s just say they have much to improve J. So started to think about using list.GetItems(query).GetDataTable() and building a user control with a DataGrid, but then the look and feel would be very difficult to achieve.

So I went looking in the Sharepoint API documentation for what could help me, and I found the “light”… SPList.RenderAsHtml().


Building the Web Part:

 

First declare, instantiate and add to the Web Part, the objects which are going to be the user interface objects:

protected PlaceHolder CtPlaceHolder;

protected Literal CthtmContainer;

protected DropDownList CtddViewsInList;

protected override void CreateChildControls()

        {

            CtPlaceHolder = new PlaceHolder();

            CthtmContainer = new Literal();

            CthtmContainer.EnableViewState = false;

            CtddViewsInList = new DropDownList();

            CtddViewsInList.ID = "dd";

            CtddViewsInList.AutoPostBack = true;

             CtPlaceHolder.Controls.Add(CtddViewsInList);

            CtPlaceHolder.Controls.Add(CthtmContainer);

            this.Controls.Add(CtPlaceHolder);

        }

 

There is a Literal that will have the html returned by the SPList.RenderAsHtml() to be rendered in the Web Part, there is a DropDownList to be able to select which View to be shown and finally, a PlaceHolder that will contain the Literal and the DropDownList. These are the only three graphic controls we need to build the user interface.

A custom property named ListName was also created, so we can configure what list we will be working with, in a next post maybe I will show how to dynamically load all the SPLists existing in the current Web into a DropDownList so we can choose from the list, but in this example the name of the list to use will be written in a Custom Property Textbox. For more information on how to use Custom Properties refer to http://msdn.microsoft.com/en-us/library/dd584174.aspx.

   [Category("Custom Properties")]
   [WebPartStorage(Storage.Personal)]

   [FriendlyNameAttribute("List to view")]
   [Description("Write the name of the list.")]
   [Browsable(true)]
   [DefaultValue("Documents")]
   [XmlElement(ElementName="ListName")]

public string ListName
   {
     get
     {
        return _list;
     }

     set
     {
        _list = value;
     }
   }

 

Then an SPWeb object is created from the current context and a reference the SPList object to work with is obtained:

   using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())

    {

       SPList list;

          try

            {

              list = web.GetList(ListName);

            }

                                                               

 

 

The next step is to load the list of views from the SPList into the DropDownList

  

foreach (SPView view in list.Views)

{

    CtddViewsInList.Items.Add(new ListItem(view.Title, view.ID.ToString()));

 }

                                    

 

It is also necessary to create a SPQuery based on the selected view so it can be used as the parameter to the SPList.RenderAsHtml(query As SPQuery) method.

  

SPQuery query;

SPView selectedView;

if (!string.IsNullOrEmpty(CtddViewsInList.SelectedValue))

    selectedView = list.GetView(new Guid(CtddViewsInList.SelectedValue));

else

    selectedView = list.DefaultView;

 selectedView.Scope = SPViewScope.Default;

query = new SPQuery(selectedView);

 

CthtmContainer.Text = list.RenderAsHtml(query);

                                   

 

The final Result

 

Configure the Which list to use using the Modify Shared Web Part the fill the ListName property with the name of the list. In this case we will use the Documents List. 

clip_image002clip_image003

All documents View

clip_image004

Explorer View

clip_image005

 

A Custom View and the options menu for an item.

clip_image007

Some considerations

 

There are some considerations to have in mind that are important. The SPList.RenderAsHtml is really as interesting as described, and as we saw we can easily build a rich user interface with little work, but from the point of view of the user interface and the look and feel.

One may be disappointed when he wants to use some things like ordering, because ordering is not out of the box. You have the UI but the behaviour has to be implemented. In this case one would need to define the order in the SPQuery object, using the query string parameters, so the data is ordered according to the user interface selection. The same happens when you try to filter data using filter data on columns, the action is there, but the behaviour you have to implement it.

Although for these actions you have to do the behaviour implementation for the item menu shown above all the actions are out of the box and work as expected in this scenario.

Another important thing to have in mind is that this method can be potentially dangerous when used to display large sets of items. This method returns a string that may be quite big depending on the number of items of the list returned by the query, so due to the large memory consumption and fragmentation on the .NET large object heap, specially in 32Bit systems, if not used carefully it can lead to OutOfMemory Exceptions and sluggish performance.

 

Conclusion

 

As you may see this method can be very useful when you want to give the user, quick different views on the items on a list. This approach worked for me, and it respected the requirements of the scenario in hand. I enjoyed using it a lot, especially because of the time saved, not having to build the entire user interface. For the final user, the experience is also a good one, because he has a brand new feature that works right the same way as everything in SharePoint.  

Hope you enjoy this feature

See you next time!

Rui Veloso

 

Posted by ptadcs | 1 Comments

Object variable or With block variable not set: how to eradicate these tongue-twisters haunting from the past

  In a perfect world, computer applications would be syntactically and semantically correct and complete, thus exhibiting no errors nor flaws. Ours is not a perfect world, though, and even worse is that a significant part of those computer applications are still being coded in Visual Basic 6.0. Great!! This way, we are being given a huge opportunity to contribute towards that perfect world.

 

  This post is exactly about one such opportunity: getting rid of these annoying errors which you did not find while testing the code in your development environment, but once it gets under massive exercise by the end-users, they start popping like crazy. My inspiration for this post is an Active Server Pages application which calls into some Visual Basic 6.0 DLLs which, in turn, are accountable for pretty much everything going on in the application from its business layer to page rendering. That is how the VB code is getting such huge exercise and the event logs are getting filled with these VBRuntime errors.

 

  Here it is, the tongue-twister…

 

  So, what can we do about this? The error, by itself, says little about what is going on and you’re live, meaning you can’t pop in with a breakpoint from Visual Studio 6.0… Well, not from Visual Studio, but from any production debugger, you actually can. You can also instruct it to create a full memory dump every time one such error occurs, even if your application is not crashing.

 

  What do we need for that? Well, the list is short, but not necessarily easy to fulfill:

  • A production debugger, as stated above. I personally recommend the acclaimed Debugging Tools for Windows, but of course, I’m biased… By the way, the rest of the post assumes you can live with such bias…
  • Private symbols for the VB6 components. This usually means a PDB file for each module (EXE or DLL) being called when the problem occurs. Getting a perfectly matching private symbol set can be a harsh task, but if the application is still under development or maintenance, be sure to check the Create Symbolic Debug Info in the project properties before recompiling and deploying, and if possible avoid optimizations, at least temporarily.



    If the application is not under maintenance and/or the source code is not available anymore, you’re in trouble. But then again, what would you do if you found out the cause of the problem?
  • Keep the users warned that for some time, they will perceive a non-negligible lack of performance.

  Your users are warned, you have private symbols and you have chosen the Debugging Tools for Windows (wise choice!!). What next? Ok, you can use WinDbg, attach to the process, type sxe C0000005, hit F5, wait for the exception to occur, and when it does, use the .dump /ma DumpFile.dmp to dump it to a file. Let me recommend another way, which is less disruptive of user experience and will enable you to get multiple occurrences of these errors, if they happen while the debugger is attached.

 

  This error is nothing more than the VBRuntime counterpart for an Access Violation, meaning that your code is trying to access a member property or method from a non-existing object (from Nothing, in VB6 notation). So, this is what you can do:

  • Create and edit a file with the cfg extension (I’ll assume the name config.cfg).
  • Copy and paste the following contents (remove the Option tag if not under IIS and be sure to attach to a particular process later):
    <ADPlus>
      <Settings>
        <RunMode> CRASH </RunMode>
        <Option> IIS </Option>
      </Settings>
      <Exceptions>
         <Config>
           <Code> av </Code>
           <Actions1> Log;FullDump </Actions1>
         </Config>
      </Exceptions>
    </ADPlus>
  • Save the file in the same folder where the debugging tools have been installed.
  • Open a command prompt, go to that folder and run the following command cscript adplus.vbs –c config.cfg. You can also specify an output directory by using the –o option, if you feel you’ll be lacking space in your current volume.

 

 

  This will create as many full dumps as access violation occurrences and each one will have a synchronous picture of what was being called by the time it occurred. You can then open each one in WinDbg, for instance, ensuring you have your private symbols in place (the source code will also help) and with a few commands, you’ll be able to pinpoint the cause.

 

  By the way, another option would be to run a parametrized command, such as cscript adplus.vbs -crash -ce C0000005 -FullOnFirst -p <PID> (or -iis). Thanks Bruno, for the valuable input! Still, however, a configuration file will allow you to easily adapt to the circumstances along the way. For a broader discussion on how to capture the adequate set of dumps, check this great post:

    http://blogs.msdn.com/carloc/archive/2007/10/08/ok-now-how-do-i-capture-my-dump.aspx

 

  Back to the discussion at hands, let’s take a look at an example.

 

  When opening one of the dump files, this is what WinDbg is showing:

 

Windows Server 2003 Version 3790 (Service Pack 2) MP (4 procs) Free x86 compatible

Product: Server, suite: TerminalServer SingleUserTS

Machine Name:

Debug session time: Mon May 11 11:56:53.000 2009 (GMT+1)

System Uptime: 0 days 11:54:17.328

Process Uptime: 0 days 0:01:35.000

................................................................

................................................................

................................................................

........................................

Loading unloaded module list

....

This dump file has an exception of interest stored in it.

The stored exception information can be accessed via .ecxr.

(170c.153c): Access violation - code c0000005 (first/second chance not available)

eax=00000000 ebx=72e5e380 ecx=72e67cdb edx=00000001 esi=736560f4 edi=00000000

eip=0bfd304f esp=02dedb7c ebp=02dedc1c iopl=0         nv up ei pl nz na po nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202

FailingModule!failingClass::failingFunction+0x14f:

0bfd304f 8b10            mov     edx,dword ptr [eax]  ds:0023:00000000=????????

 

  We can run kbn200 and check the call stack:

 

0:024> kbn200

 # ChildEBP RetAddr  Args to Child             

00 02dedc1c 0bfd07db 0d747678 02dedc78 02dedd44 FailingModule!failingClass::failingFunction+0x14f

01 02dedd98 110136ca 0d747678 087c2fac 02dedf90 FailingModule!failingClass::FailingFunctionCaller+0x9bb

02 02dee000 77d05186 05b9bd68 05ba7aa4 08794c7c FormRender!Constructor::RenderPageFraction+0x3ea

03 02dee028 73646a6f 05b9bd68 00000024 00000004 oleaut32!tPushValJmpTab+0x102

04 02dee984 7363a0d4 05b9bd68 11011734 60030002 msvbvm60!VBStrToLong+0xcf

05 02dee9e0 7773fecb 05b9bd68 60030002 734614f4 msvbvm60!rtFindFirstFile+0x185

06 02deea18 77720fc4 086779dc 05b9bd68 02deeb50 ole32!DISPATCH_CLIENT_FRAME::Invoke+0x3b

07 02deea60 7772134a 0869b8b0 02deeba0 02deeb2c ole32!CCtxChnl::SyncInvoke2+0x70

08 02deeb18 77722ee6 0009c3b0 00104d30 02deec24 ole32!CCtxChnl::SendReceive2+0x201

09 02deec78 77741804 0869b8b4 086776dc 0d8a71cc ole32!CCtxChnl::OnCall+0x225

0a 02deec98 77740027 086776d8 02deecc0 00000006 ole32!LEGACY_INTERCEPTOR::CallIndirect+0x91

0b 02deecb8 7347d36b 8004d091 60030002 734614f4 ole32!LEGACY_INTERCEPTOR::Invoke+0x23

0c 02deed0c 73468ad1 019e4b68 0d8a71cc 60030002 vbscript!CatchIDispatchInvoke+0x46

0d 02deed4c 73468a40 0194b218 0d8a71cc 60030002 vbscript!IDispatchInvoke2+0xaf

0e 02deed88 734689f2 0194b218 0d8a71cc 60030002 vbscript!IDispatchInvoke+0x59

0f 02deee9c 7346613b 0194b218 0d8a71cc 60030002 vbscript!InvokeDispatch+0x13a

10 02deeec0 73468b57 0194b218 0d8a71cc 60030002 vbscript!InvokeByName+0x42

11 02def19c 734633e0 00000000 00000000 0194b218 vbscript!CScriptRuntime::Run+0x2587

12 02def294 734637d1 00000000 00000000 01934530 vbscript!CScriptEntryPoint::Call+0x5c

13 02def2ec 7347e882 0194d190 00000000 00000000 vbscript!CSession::Execute+0xb4

14 02def374 7347d17c 00000000 00000000 01cc27f4 vbscript!NameTbl::InvokeEx+0x526

15 02def3c4 73467353 019e4b68 0194ff80 0b76294c vbscript!CatchIDispatchExInvokeEx+0x43

16 02def400 734672c5 0194b218 0194ff80 0b76294c vbscript!IDispatchExInvokeEx2+0xa6

17 02def438 73466209 0194b218 0194ff80 0b76294c vbscript!IDispatchExInvokeEx+0x56

18 02def548 7346613b 0194b218 0f76dbf0 0b76294c vbscript!InvokeDispatch+0x101

19 02def56c 73466f6c 0194b218 0194ff80 0b76294c vbscript!InvokeByName+0x42

1a 02def848 734633e0 00000000 00000000 0194b218 vbscript!CScriptRuntime::Run+0x262b

1b 02def940 734637d1 00000000 00000000 00000000 vbscript!CScriptEntryPoint::Call+0x5c

1c 02def998 73463b9c 0f5da808 00000000 00000000 vbscript!CSession::Execute+0xb4

1d 02def9e8 73461849 00000000 00000000 709e19c0 vbscript!COleScript::ExecutePendingScripts+0x13e

1e 02defa04 709e2bfa 023c2708 023c2708 01cc27f0 vbscript!COleScript::SetScriptState+0x150

1f 02defa30 709e2bbc 00000000 709e19c0 02defb38 asp!CActiveScriptEngine::TryCall+0x19

20 02defa6c 709e2af2 00000000 6472474e 01fc22b8 asp!CActiveScriptEngine::Call+0x31

21 02defa88 709e29f6 02defb0c 00000000 00000000 asp!CallScriptFunctionOfEngine+0x5b

22 02defadc 709e2921 024c2950 00000000 02defb68 asp!ExecuteRequest+0x17e

23 02defb44 709e24e0 024c2950 01fc22b8 02defb68 asp!Execute+0x24c

24 02defb98 709e244a 00000000 00000000 0b078ba0 asp!CHitObj::ViperAsyncCallback+0x3f0

25 02defbb4 4a77b5ea 02042cc8 0009c240 02defd74 asp!CViperAsyncRequest::OnCall+0x92

26 02defbd0 77720d30 0b078ba0 00104c04 00000000 comsvcs!CSTAActivityWork::STAActivityWorkHelper+0x32

27 02defc1c 777217dc 00000000 00104c04 4a77b5b8 ole32!EnterForCallback+0xc4

28 02defd7c 776f03b4 02defc54 4a77b5b8 0b078ba0 ole32!SwitchForCallback+0x1a3

29 02defda8 7769c194 00104c04 4a77b5b8 0b078ba0 ole32!PerformCallback+0x54

2a 02defe40 7772433a 0009c240 4a77b5b8 0b078ba0 ole32!CObjectContext::InternalContextCallback+0x159

2b 02defe60 4a77b78c 0009c240 4a77b5b8 0b078ba0 ole32!CObjectContext::DoCallback+0x1c

2c 02defecc 4a77bcf2 001014b0 00101490 086d6444 comsvcs!CSTAActivityWork::DoWork+0x12d

2d 02defee4 4a77c7de 0b078ba0 00000001 00101490 comsvcs!CSTAThread::DoWork+0x18

2e 02deff04 4a77cabf 00000000 0190ca48 0190c880 comsvcs!CSTAThread::ProcessQueueWork+0x37

2f 02deff84 77bcb530 00101490 00000000 00000000 comsvcs!CSTAThread::WorkerLoop+0x190

30 02deffb8 77e64829 0190c880 00000000 00000000 msvcrt!_endthreadex+0xa3

31 02deffec 00000000 77bcb4bc 0190c880 00000000 kernel32!BaseThreadStart+0x34

 

  Since we’re sure we have private symbols, we can have the variables displayed with dv /t.

 

0:024> dv /t

void * Me = 0x0d747678

long * intArg = 0x02dedc78

wchar_t ** failingFunction = 0x02dedd44

Boolean unnamed_var1 = False (0)

long unnamed_var1 = 0

long unnamed_var1 = 48159737

long unnamed_var1 = 0

struct Variant unnamed_var1 = struct Variant

struct Variant unnamed_var1 = struct Variant

void * unnamed_var1 = 0x00000000

wchar_t * unnamed_var1 = 0x00000000 ""

wchar_t * unnamed_var1 = 0x00000000 ""

wchar_t * unnamed_var1 = 0x00000000 ""

wchar_t * unnamed_var1 = 0x00000000 ""

wchar_t * unnamed_var1 = 0x000dc434 "//NodeToBeFound[@blnCheck='TRUE'][@id='60']/@Attibute"

wchar_t * unnamed_var1 = 0x0b3e9d3c "//NodeToBeFound[@blnCheck='TRUE'][@id='60"

wchar_t * unnamed_var1 = 0x05b44844 "60"

void * objXMLTipos = 0x036381c0

wchar_t * xslt = 0x00000000 ""

wchar_t * failingFunction = 0x00000000 ""

 

  Here’s the (sanitized) code excerpt, matching the output above:

 

Private Function failingFunction (intArg As Long) As String

        Const cstrMethodName As String = "failingFunction"

        Const cstrTypesPath As String = "../config/EntityTypes.xml"

 

        On Error GoTo ErrorHandler

       

        Dim objXMLTypes As MSXML2.DOMDocument

        Dim xslt        As String

       

        Set objXMLTypes = mobjOpenXMLFile(mobjASPContext.Server.MapPath(cstrTypesPath))

        xslt = objXMLTypes.selectSingleNode("//NodeToBeFound[@blnCheck='TRUE'][@id='" & intArg & "']/@Attribute").Text

        failingFunction = xslt

       

ErrorHandler:

        Set objXMLTypes = Nothing

       

        If Err.Number <> 0 Then

          LogError vbLogEventTypeError, cstrModuleName, cstrMethodName, Err.Description

          RaiseError cstrModuleName, cstrMethodName, Err.Description

        End If

End Function

 

  Having the source code copied to my Source File Path in WinDbg, it promptly points us out that the instruction pointer was at the highlighted line when the access violation occurred. Reaching there without any source code is possible, you'd need to unassemble the function (using the uf command) and manually walk the assembly code back from the instruction pointer (0bfd304f) and checking the context - registers and memory - along the way. Though that can be fun, we'd be deep diving into MSXML code and the post would probably lose its main focus.

 

  Anyway, as you can see from the variables above, there is a string matching the concatenation of the tokens which form the XML query, meaning that the argument was 60. You could also get that from the long * intArg = 0x02dedc78 pointer, by issuing the command

 

0:024> dt long 0x02dedc78

60

 

  After having opened the EntityTypes.xml configuration file, I quickly realized there was no such content matching the query (no node named NodeToBeFound having the blnCheck set to true and an id of 60). By trying to access the Text property of Nothing, the access violation occurs and so the root cause has been found.

 

  As you can see, the cause was a very simple and straightforward one, but you’d probably spend a lot of time trying to figure it out with printf-like techniques, whereas using a production debugger such as this one, you’d find it in almost no time at all.

 

  Till next time,

 

    Manuel Oliveira

Posted by ptadcs | 0 Comments
Filed under:

How to Enable IE 8 Compatibility View for your whole Web site or for specific Web site directories

 

With the release of Internet Explorer 8, many customer sites suddenly had rendering errors and problems displaying the site correctly.

http://www.microsoft.com/windows/Internet-explorer/default.aspx

 

In order to avoid expensive and time consuming corrections Internet Explorer 8 has a new functionality called Compatibility View which enables the browser to emulate Internet Explorer 7.

 

Internet Explorer 8 Compatibility View

http://www.microsoft.com/windows/internet-explorer/features/enhanced-navigation.aspx

 

The question many customers asked is ”How can I force the client browser to use the Compatibility View when they visit our site? So that the customer doesn’t have to activate it on the client side.”

Web Developers and Site Administrators can configure IIS and their sites to tell Internet Explorer 8 to automatically Emulate Internet Explorer 7 when they visit their site or just specific WebPages.

This is done by adding a custom HTTP Header to the IIS and the website web.config or to add a meta tag to specific pages. The HTTP Header is interpreted by the Internet Explorer 8 which will activate the compatibility view. All other browsers will simply ignore this custom HTTP Header.

 
X-UA-Compatible: IE=EmulateIE7
 

Add the custom HTTP response header in IIS

To add a custom HTTP response header at the Web site level, at the folder level, or at the virtual directory level in IIS, follow the steps for the version of IIS that you are using.

IIS 7 on a Windows Server 2008-based Web server

    1. Start IIS Manager. To do this, click Start, click Run, type inetmgr, and then click OK.

    2. Under Connections, double-click the server that you want, and then double-click Sites.

    3. Click the Web site, the folder, or the virtual directory where you want to add the custom HTTP response header.

    4. Under <Web site name> Home, double-click HTTP Response Headers in the IIS section.
    5. Note The <Web site name> placeholder refers to the name of the Web site.

    6. Under Actions, click Add.

    7. In the Name box, type X-UA-Compatible.

    8. In the Value box, type IE=EmulateIE7.

    9. Click OK.

       

      IIS 6 and earlier versions

      1. Click Start, click Run, type inetmgr.exe in the Open box, and then click OK.

      2. Expand the server that you want, and then expand Web Sites.

      3. Right-click the Web site, the folder, or the virtual directory that you want, and then click Properties.

      4. On the HTTP Headers tab, click Add under Custom HTTP headers.

      5. In the Custom header name box, type X-UA-Compatible.

      6. In the Custom header valuebox, type IE=EmulateIE7.

      7. Click OK two times.

       

      Add the custom HTTP response header in the Web.config file

      To add this header to the Web.config file, create or revise the Web.config file as follows.

    <?xml version="1.0" encoding="utf-8"?>
      <configuration>
         <system.webServer>
               <httpProtocol> 
                   <customHeaders> 
                        <clear /> 
                        <add name="X-UA-Compatible" value="IE=EmulateIE7" /> 
                   </customHeaders> 
               </httpProtocol> 
         </system.webServer> 
      </configuration>

    Note Add this new or revised Web.config file to each Web directory in which you want to use compatibility mode.

     

    More information can be found in KB 968499, about configuring the Compatibility View.

     

    KB 968499 - Advanced solutions: Some Web sites may not be displayed correctly or work correctly in Windows Internet Explorer 8

    http://support.microsoft.com/kb/968499

     

    Pedro M. Pinheiro

    Posted by ptadcs | 2 Comments

    Silverlight and "Cover Flow" – Revisited (Part III)

    On my previous post I wrote about the complexity of implementing perspective projections with Silverlight 2 since it only supports 2D affine transforms.

    Well, as you surely already know by now, with Silverlight 3 you’ll be able to apply 3-D projections to any Silverlight UIElement using "perspective transforms", this is, non-affine transforms of objects in space. We can’t yet fully project a three-dimensional object onto a two dimensional plane since UIElements are 2D but we can project them on a 2D plane as if they lived on a 3D world.

    I won’t go into much detail here since the pre-release documentation about this subject is available on msdn and it’s extremely rich in illustrations, samples and detail.

    What I would like to show in this post is how this can be applied on our cover flow sample and, especially, how can we “amplify” the perspective distortion. Let’s start then.

    With Silverlight 3 it’s so simple that it’s almost not fun anymore.

    Instead of implementing Polygon triangulation and Texture mapping we just have to apply the right PlaneProjection to our Cover object.

    Something like this (Y axis rotation):

    <Rectangle x:Name="MyRect" Width="100" Height="100" Fill="Blue" Opacity="0.7" >
           <Rectangle.Projection>
                 <PlaneProjection RotationX="0" RotationY="-45" RotationZ="0"></PlaneProjection>
          </Rectangle.Projection>
    </Rectangle>

    And, as would be expected, we can animate it using a standard storyboard.

    <Storyboard x:Name="MyStoryboard">
           <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="MyRect" Storyboard.TargetProperty="(UIElement.Projection).(PlaneProjection.RotationY)">
                    <EasingDoubleKeyFrame KeyTime="00:00:00" Value="-45"/>
                    <EasingDoubleKeyFrame KeyTime="00:00:05" Value="45"/>
           </DoubleAnimationUsingKeyFrames>
    </Storyboard>

    End of story, right? Well, I found it to be not as impressive as I thought it would be. It lacks drama… action. Something seems different.

    That’s because the original Coverflow UI has a greater perspective distortion. In our sample we have perspective too but it is almost unnoticeable.

    Notice how the closest edge of the rectangle is just a little larger than the distant one.

    We can produce a stronger, more exaggerated perspective effect applying a wider angle of view.

    When we wide an angle of view the relative sizes of objects are exaggerated (when we narrow an angle of view the objects are all nearly the same relative size and you lose the sense of depth). These effects are very perceptible when you use lens of different focal lengths on a camera.

    Note: It’s hard to define what a “normal” angle of view is. Our brain is able to interpret a wide range before our perception “fails” to recognize an object because of its strong distortion. See Angle of View vs. Perspective Distortion.

    Back to our subject… Since we can’t change our angle of view in Silverlight 3 (as far as I know) how can we dramatize the perspective distortion?

    We can do it by artificially increasing the object on a single dimension (X in this sample) and rotating it strongly on other axis (Y in the sample).

    <Canvas x:Name="MyCanvasPerspectiveAmplified" Width="100" Height="100">
           <Canvas.Projection>
                  <PlaneProjection RotationX="0" RotationY="-79.6" RotationZ="0" LocalOffsetX="-120" />
           </Canvas.Projection>
           <Rectangle Width="100" Height="100" Fill="Red" Opacity="0.5">
                  <Rectangle.RenderTransform>
                         <ScaleTransform ScaleX="4"/>
                  </Rectangle.RenderTransform>
           </Rectangle>
    </Canvas>

    Producing:

    See the difference:

    Sure, it’s not a “pretty” thing to do, but do you prefer triangulation & texture mapping?

    If you found out a different way of doing it please tell me.

    Pedro Fortes

     

    Updated 2009-04-27:

    Willow pointed out that someone has already addressed the Cover Flow interface with Silverlight 3.
    You can check it here: http://matarillo.com/blogdata/PseudoCoverFlow (it is in Japanese).
    Thank you for that.

    The solution the author adopted here to have a greater depth was slightly different (far better in my opinion):
    Here we have an outer canvas which does the scaling on both dimensions while the inner projected object has an increased (and proportional) size.
    Something like this:

    <Canvas>
      <Canvas.RenderTransform>
        <TransformGroup>
          <ScaleTransform ScaleX="0.20" ScaleY="0.20"></ScaleTransform>
          <TranslateTransform X="150" Y="100"></TranslateTransform>
        </TransformGroup>
      </Canvas.RenderTransform>
      <Rectangle x:Name="MyRect" Width="500" Height="500" Fill="Green" Opacity="0.7" >
        <Rectangle.Projection>
          <PlaneProjection RotationX="0" RotationY="-45" RotationZ="0"></PlaneProjection>
        </Rectangle.Projection>
      </Rectangle>
    </Canvas>

     

    Posted by ptadcs | 1 Comments
    Filed under:

    Reusing web user controls

    “Why”?

     

    With this post I want to demonstrate how to reuse Web User Controls in multiple web projects to avoid the duplication of code and interface. How many times many of us needed a Web User Control created in another web project, and use it directly in the project you are working on? The first temptation is to copy the user control to the new web project, but then your conscience is shouting inside you “you should not be doing that”, you try to ignore and it fades, and then you find a bug or make that control a tiny bit better and you have to do it as many times as you have made a copy, then it returns (the conscience) saying “you should not have done that” J.

    The user control library

     

    To start with, let us create a Web User Control Library. To do this we create a new project in Visual Studio using ASP.NET WebApplication and named it MyUserControlLibrary like the image below and then click OK:

     

    The next step is to delete from the project MyUserControlLibrary the files Default.aspx and Web.config, we won´t be needing them in this project.
    Next we add to the project a new Web User Control, name it MyReusableUserControl.ascx and click the Add button.

     

     In this example this user control is going to be a text field validated to only allow numbers between 1 and 200 and has a label whose text we can change. To do this we create a public property whose name is Caption.

          public string Caption

            {

                get

                {

                    return lblCaption.Text;

                }

                set

                {

                    lblCaption.Text = value;

                }

     

            }

     

    And the reusable user control is ready.

    Prepare to use the MyUserControlLibrary

     

    To use the user control we will need to add a new ASP.NET WebApplication to the solution and name it
    MyTestWebApplication, then add to MyTestWebApplication a new Web User Control and call it MyTestWebUserControl.ascx. We will also add to MyTestWebApplication a folder with the name UserControls for future use. The final solution layout should look like the image below.

     

    There are several ways to reuse the user control library in other projects, like managing the user control library in a different solution or use the project library in the same solution you are working, in this case we go with the second choice.

    Within MyTestWebApplication we add a reference to the User Control Library project. To do that we right click on the references node and click Add reference –> Projects, select the project MyUserControlLibrary and then click OK.

     Now right click on MyTestWebApplication and select Properties and then the Build Events Tab. Here we will do the pre-build event command for this project. The command will copy the *.ascx from the MyUserControlLibrary to the local UserControls folder created earlier, remember. This way the .ascx files will be accessible to be used in the project, but will not be added to the project itself, this way they can be easily excluded from the source control of the project and always updated. The command should look like this:

    copy $(SolutionDir)\MyUserControlLibrary\*.ascx$(ProjectDir)\UserControls\

      Another way to do this is to use MSBUILD to do the job. For this you have to edit the Project file MyTestWebApplication.csproj in notepad for example which is a XML file. Once the file is opened you should look for the fallowing commented area.

    <!-- To modify your build process, add your task inside one of the targets below and uncomment it.

           Other similar extension points exist, see Microsoft.Common.targets.

      <Target Name="BeforeBuild">

      </Target>

      <Target Name="AfterBuild">

      </Target>

      -->

     In this case we want to use the BeforeBuild target and we want to add a MSBuild task inside this target to copy the .ascx files inside our UserControls directory. To do this we are creating a new ItemGroup, defining from where and what files are we going to copy. The best way is to find the last </ItemGroup> tag and add the following next below it.

    <ItemGroup>

        <MyCustomReusableASCX Include="$(SolutionDir)\MyUserControlLibrary\*.ascx" />

      </ItemGroup>

     Next we add the copy task to the before build Target just like this.

    <Target Name="BeforeBuild">

    <Copy SourceFiles="@(MyCustomReusableASCX)" DestinationFolder="@(MyCustomReusableASCX->'$(ProjectDir)\UserControls\')" />

     </Target>

     Save the file and MSBuild as everything he needs to copy the .ascx to the UserControls folder.

    This will have exactly the same effect as the copy command on the pre-build event command but using the MSBuild, but this was a chance to show you a tiny bit of MSBuild J.

    At the moment what we have to do is to build the solution and if everything goes right, we will have no errors, and the MyUserControlLibrary.ascx will be waiting to be used inside of the UserControls Folder in the Web Application. To be able to see the user control we have to select the MyTestWebApplication project and activate the option Show All Files on the top of the Solution Explorer. The Solution Explorer should look like the image below. 

     

    MyTestWebUserControl

    We could use MyReusableUserControl.ascx directly on Default.aspx but instead we will use MyTestWebUserControl.ascx to embed MyReusableUserControl.ascx, and then use MyTestWebUserControl.ascx, that is the combination of both in the Default.aspx page.

    This user control will have two labels and two text boxes (Fist Name, Last Name) and our custom user control (MyReusableUserControl.ascx) that will accept only as an input, a number between 1 and 200. The aspect of MyTestWebUserControl.ascx looks like this:

     

    Notice that the MyReusableUserControl.ascx appears highlighted. To use this user control in MyTestWebUserControl.ascx we simply dragged the user control from the folder UserControls to the MyTestWebUserControl.ascx design view. In Visual Studio 2005 and 2008 user controls are supported in WISIWYG (What I See Is What You Get) so it´s possible to see the controls rendered in the design view instead of the grey box in Visual Studio 2003.

    Putting it all together      

    We will use the page Default.aspx to put our example together. To do this we simply drag MyTestWebUserControl.ascx to the Default.aspx design view, and our interface is almost ready. The next step is to use the final user control in Default.aspx. We also added a BulletedList to the page and a Button.

     

    And then add the following code to the OnClick event of the Submit Button:

    protected void btSubmit_Click(object sender, EventArgs e)

            {

     

                BulletedList1.Items.Clear();

                if (Page.IsValid )

                {

                                  BulletedList1.Items.Add(((TextBox)MyTestWebUserControl1.FindControl("txtFirstName")).Text);

                    BulletedList1.Items.Add(((TextBox)MyTestWebUserControl1.FindControl("txtLastName")).Text);

     

                    MyUserControlLibrary.MyReusableUserControl uc = (MyUserControlLibrary.MyReusableUserControl)MyTestWebUserControl1.FindControl("MyReusableUserControl1");

                    BulletedList1.Items.Add(((TextBox)uc.FindControl("txtNumber")).Text);

                }

            }

     


    The final Result is:

     

    Just to be easier to understand, below is an image with the parts which the final page is built with.

     

    Voilá! And the example is complete. Reuse your code and I promise you, your conscience will leave you aloneJ.

     

    See you next time!

    Rui Veloso

    Posted by ptadcs | 0 Comments
    Filed under: ,

    HTTP Error 401.5 – Unauthorized: a very plausible scenario

    Recently, my customer started complaining that an externally-facing web site was not working properly. Apparently no changes had been made to the web site… This is very common in the field: nothing happens and software starts decaying in what seems to be a Half-Life phenomena. However, the site had been put offline for database maintenance purposes. How? Well, the external customers had to know what was going on, so they decided to do the following:

    ·         Copy the index.asp file to the desktop as a backup;

    ·         Change the published version of index.asp in-place, stating the application was unavailable;

    ·         After the maintenance had finished, the index.asp file on the desktop was moved back to its original location, overwriting the maintenance-mode version.

     

    Nothing weird, so far, right?

     

    Well, let me tell you the 3 steps above resulted in the following:

     

     

     

      So, what went wrong? Well, there’s a small detail which may help understand the problem… In fact, as this is an externally-facing web site, it has been configured for anonymous access, which means the IUSR_<computername> will be used as the security principal for every site access.

     

      As a troubleshooter, I keep a flash drive with the tools of the trade. I even keep a 10+ folder for the most used tools, as you can see below.

     

     

      Well, back to the issue… I started the Process Monitor and quickly found out an ACCESS DENIED while accessing the index.asp file. Here are the details of that error:

     

     

      Ok, so the anonymous account is not able to access the file. How so?? It did access it successfully in the past. The fact is that the file ACL is not considering the anonymous logon as it should:

     

     

     

      So the problem has been found. What led to it? Well, let us replay the bulleted list above in slow-motion:

    ·         Copy the index.asp file to the desktop as a backup;
    As the file is being copied, a new file is created on the desktop with a brand-new ACL (by now, I’m guessing you don’t need to read any further). This ACL will have a set of permission entries which are inherited from the desktop folder.

    ·         Change the published version of index.asp in-place, stating the application was unavailable;
    This step is OK and it has no impact whatsoever on ACLs…

    ·         After the maintenance had finished, the index.asp file on the desktop was moved back to its original location, overwriting the maintenance-mode version.
    It was this final move that broke things up. By moving the file back into its original location, the permission entries would have lost their inheritance. In these circumstances, the Operating System replaces the inherited permissions by entries with no inheritance. The purpose of this step is to ensure that the security settings are not lost during the file move. However, it induces the nasty effect of not matching the original entries and keeping the site unavailable in an ugly way.

     

      In my humble opinion, this could happen to anyone, but Windows cannot be blamed for this situation. File operations such as copying or moving have their own semantics and they have been in place long enough for us to start doubting of the wise decisions made while making them available to users, right? What else can I tell you? Well, avoid backing up your web files on servers desktops…

     

      Till next time,

     

        Manuel Oliveira

    Posted by ptadcs | 0 Comments
    Filed under:

    Where can the new Ignoreisactive Parameter for the STSADM Sync Operation be used?

     

    After the Microsoft Office SharePoint Server build 12.0.6314.5000, the stsadm Sync operation introduced a new parameter – “ignoreisactive”, specially designed for the issue described in the following article: http://support.microsoft.com/default.aspx/kb/952683 .

    This issue occurs because the tp_IsActive flag is false (0) for the user in the userinfo table in thecontent database of the Web Application (by default only active user profile is synchronized).

    Regarding the article, if you experience this problem (The welcome name on a site is not changed as expected after you edit the name of a user profile in SharePoint Server 2007), the solution is to install the update, but :

    After you apply the update, the welcome name on the site is still not changed as expected. However, if you add a new user after you apply the update, this name will be listed as the welcome name.

     

    So, do I really need to delete and create the user again?

     

    No, you can use the ignoreisactive parameter, as follows:

    1. Ensure you are running MOSS version 12.0.6314.5000 or higher

    (New parameter added for stsadm -o sync)

    2. Run stsadm -o sync -ignoreisactive 1

    (All profiles we be synchronized, the flag will be ignored)

    3. Run stsadm -o deleteolddatabases 0

    (All synchronization logs will be deleted >> next profile sync run will be a "full sync")

     

    After that, with the next profile synchronization job execution, all profiles will be synchronized. To check this, you can run stsadm -o listolddatabases 0 and search for the GUID of the affected content database.

    However, if you don’t want to wait for the next profile execution job, you can use stsadm –o sync –synctiming m:5 command (http://technet.microsoft.com/en-us/library/cc263196.aspx) to force the profile synchronization job to be executed every 5 minutes. In a productive environment please changes back the value to 1 hour or you may experience a performance decrease!

    Note that this workaround is valid to all changes in AD properties (not only the welcome name).

    See you next time …

    Nuno Nunes

    Posted by ptadcs | 5 Comments
    Filed under: ,

    Authorization Manager … Why not?

    One of this days, when I was just talking with some of my colleagues we start wandering about Authorization mechanisms, and rapidly they evolved to all sort of techniques.

    They talk about COM+ Roles, they talked about ASP.NET Roles, they talked about Passport Accounts, and they even talked about ADAM.

    So after awhile I just said: “Hey, and what about Azman?”

    Everyone just look at me, almost blank, and I was able to realize that there is a lot of ignorance about the AzMan.

    This was a big surprise for me, since I always considered AzMan one of the most interesting mechanisms to implement Authorization. It’s easy to use, it’s reliable, it’s highly customizable and extensible and the performance is great.

    So this time I decided to write a little about the Authorization Manager.

    I rapidly realize that I don´t need to write a long a very technicall article about the AzMan, since there is a lot of that on the Internet, I would give some directions for that in the end of this article.

    So, it was not a question of lack of technical information available that cause this strange obscurity about the AzMan.

    Also, theres was not for lack of interest in the Microsoft, because the AzMan will have a major role in the Longhorn OS.

    So I would say that mainly the Developer community does not know much about the AzMan because they can see the value for them in the AzMan.

    So let’s try to do that

     

    I’m a Developer, and this is what I need

    Let’s start by saying what you, as a Developer, need.

    If you ask me, I would say, that I need an Access control functionality for applications that is simple and secure.

    I also need to improve the security of my products by ensuring proper integration with AD and windows security technologies.

    And finally I absolutely need to reduce administrative management requirements for my software – e.g. improving their value proposition to clients

    I would say that everyone will agree that those are obvious needs for all of us.

    What about the scenarios that I usually have to face? Let’s think also a little about this.

    Well, I have to protect access to Web-based, collaboration, and LOB applications (e.g. development team sites)

    I also have to provide a secure, automated access for trusted groups, e.g. clinician access to patient healthcare data

    Of course, I also have to provide audit records of who accessed what data and when.

    Agree?

    So after this where it goes the question that everyone is asking now … I hope:

     

    What is Authorization Manager?

    This is one is easy, you can use the Live Search and put that question in and you will get a lot of results answering.

    For me, the answer is quite simple; Authorization Manager is roughly a component of Windows that provides an easy-to-use authorization framework for Web-based and line-of-business applications.

     It provides role-based access control, e.g. the ability to control access to applications based on Active Directory group policy or another set of role-based permissions.

    Visually is something like this

     

     

    In terms of structure the primary components of the Authorization Manager are as follows:

    ·         We have a role-based user interface, which determines end-user access based on user or group permissions in AD or SQL

    ·         We have a management interface, which enables Administrators to configure access control for groups and individuals, manage roles, and view audit logs

    ·         And we also have, of course, an enforcement functionality, which enables Administrators to enforce organizational policy rules.

     

    So, what’s in there for me?

    ·         With it, I now have a Simple Access Control Development Model.

    It helps me reducing the software development costs by providing manageable, centralized administration and natural development model for my Web and line-of-business applications.

    Also, it gives us the ability to define operations, tasks, roles, and business rules with a natural development model.

    ·         Platform Services in Longhorn Reduce Development Scope

     

    That’s true; AzMan will have a big presence in the new Longhorn Operating System.

     

    ·         It will simplifies the Deployment, Configuration, and Management process for me

    Through enabling a security policy based on a company's organizational structure and business rules by defining user roles

    Through the ability to define operations, tasks, and roles using flexible authorization rules

    By giving a centralized configuration and management it will help reduce the total cost of ownership

     

    ·         Increases Security through Access Control

    Now, the Access controls are based on security policy

    The User identity is the basis for the access

    The privileges are updated automatically as users change roles

     

    How it works?

    The concept in is essence is very simple, you are receiving a simplified development model for managing flexible groups, business rules, and store authorization policies.

    The AzMan can though provide a role-based access control for applications, it determines user access based on Active Directory or SQL permissions.

    You can also extend existing directory services with a simple access control model.

    And finally, you can be easily integrated into most applications.

     

    So I hope I was able to capture your interest and awake your curiosisty, if so, now you can dive on the technical details about the AzMan, and for that you will find a lot of resources, here it goes some of them.

    Sia next time, jp.

     

     

    Resources on the Web:

     

    ·         Authorization Manager Blog

    http://blogs.msdn.com/azman

     

    ·         Authorization Manager Developer Whitepaper

    http://msdn2.microsoft.com/en-us/library/aa480244.aspx

      

    ·         Authorization Manager Whitepaper

    http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/management/athmanwp.mspx

      

    ·         Platform SDK Documentation

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/authorization_manager_model.asp

      

    ·         DEV: Keith Brown MSDN Article (Sample included): Use Role-Based Security in Your Middle Tier .NET Apps with Authorization Manager

    http://msdn.microsoft.com/msdnmag/issues/03/11/AuthorizationManager/

      

    ·         Server Watch Tutorial: Exploring Windows 2003 Security: Authorization Manager

    http://www.serverwatch.com/tutorials/article.php/3287431

      

    ·         Authorize It - Use Role-Based Security in Your Middle Tier .NET Apps with Authorization Manager

    http://msdn.microsoft.com/pt-pt/magazine/cc300469(en-us).aspx

     

    Under the hood with live debugging

    Often, i get the question on how to see what the framework is doing, how to set breakpoints, do live debugging in order to understand what is under the hood.

    So, I decided to write on the subject and about the approach I usually take when doing live debugging

    Scenario
    .Net application that provides a host for workflow-based services.

    Tools Required
    Debugging Tools for Windows
    Lutz Reflector
    SOS debugger extension

    First, open windbg and attach to the process. After attaching, the debugger will break. So, first question.

    How do we find where to stop first? It depends J,  but usually I use Lutz Reflector to get the entry point. So in our sample, I open WFService.exe (my application) in Reflector and see that Main is the entry point (this applies to any method you want to break into).

    NOTE: To get the correct syntax look at lower left corner in Reflector where it shows declaring type and assembly name.

    Now that we found what we were looking for, here comes question number two.

    How to set the breakpoint? Let’s go back to windbg. First step is to load SOS extension. Then we will use !bpmd command to set our breakpoint.
    Syntax is: 
             !BPMD <module name> <method name> 
             !BPMD -md <MethodDesc>

    Also, help on BPMD is very detailed so in case of any doubt: !help !bpmd

    So, let’s set our breakpoint on WFService.Program.Main

    0:003> .loadby sos mscorwks
    0:003> !bpmd WFService.exe WFService.Program.Main
    Found 1 methods...
    MethodDesc = 000007ff000433f0
    Setting breakpoint: bp 000007FF00180120 [WFService.Program.Main(System.String[])]

    Now, press g (go) and let our breakpoint be hit. After our breakpoint got hit I usually look at callstack: !clrstack.

    Note: Clrstack shows in the first two columns ESP and EIP.

    To set further breakpoints we can follow the same approach as before, but sometimes we want to set breakpoints not only on a method but also inside the method.
    In these cases, one other approach is required (also I find it faster than going to Reflector) and that is to use the command BP (for details on breakpoints and different commands do: .hh bp on the debugger)

    Lets un assembly the method we are in. (e.g. breakpoint right before calling the constructor below)

    WorkflowServiceHost host = new WorkflowServiceHost(typeof(Workflow1), new Uri[0]);

    In green is EIP (after doing !clrstack we get this address).
    Uf is the command to un assembly function (further details .hh uf in windbg)

    0:000> uf 000007ff`00180182
    WFService!WFService.Program.Main(System.String[])+0x62
       37 000007ff`00180182 48894528        mov     qword ptr [rbp+28h],rax
       37 000007ff`00180186 90              nop
       38 000007ff`00180187 48b9c8600400ff070000 mov rcx,7FF000460C8h
       38 000007ff`00180191 e8bad458f5      call    mscorwks!RuntimeTypeHandle::GetRuntimeType (000007fe`f570d650)
       38 000007ff`00180196 48894530        mov     qword ptr [rbp+30h],rax
       38 000007ff`0018019a 48b91ab704f2fe070000 mov rcx,offset System_ni+0x4b71a (000007fe`f204b71a)
       38 000007ff`001801a4 33d2            xor     edx,edx
       38 000007ff`001801a6 e8b5fc58f5      call    mscorwks!JIT_NewArr1OBJ_MP_InlineGetThread (000007fe`f570fe60)
       38 000007ff`001801ab 488bd8          mov     rbx,rax
       38 000007ff`001801ae 48b9f85a23e5fe070000 mov rcx,offset System_WorkflowServices_ni+0x165af8 (000007fe`e5235af8)
       38 000007ff`001801b8 e813fb58f5      call    mscorwks!JIT_TrialAllocSFastMP_InlineGetThread (000007fe`f570fcd0)
       38 000007ff`001801bd 48894538        mov     qword ptr [rbp+38h],rax
       38 000007ff`001801c1 4c8bc3          mov     r8,rbx
       38 000007ff`001801c4 488b5530        mov     rdx,qword ptr [rbp+30h]
       38 000007ff`001801c8 488b4d38        mov     rcx,qword ptr [rbp+38h]
       38 000007ff`001801cc e8ffccfae4      call    System.ServiceModel.WorkflowServiceHost..ctor(System.Type, System.Uri[]) (000007fe`e512ced0)
       38 000007ff`001801d1 4c8b5d38        mov     r11,qword ptr [rbp+38h]
       38 000007ff`001801d5 4c895d08        mov     qword ptr [rbp+8],r11
       40 000007ff`001801d9 488b4508        mov     rax,qword ptr [rbp+8]
    (…)
       59 000007ff`0018023f 488da588000000  lea     rsp,[rbp+88h]
       59 000007ff`00180246 5d              pop     rbp
       59 000007ff`00180247 5b              pop     rbx
       59 000007ff`00180248 f3c3            rep ret

    So i will set a breakpoint right before ctor gets called (see yellow above and below)

    0:000> bp 000007ff`001801cc
    0:000> g
    Breakpoint 0 hit
    WFService!WFService.Program.Main(System.String[])+0xac:
    000007ff`001801cc e8ffccfae4      call    System.ServiceModel.WorkflowServiceHost..ctor(System.Type, System.Uri[]) (000007fe`e512ced0)

    Now, all depends on what we want to do. If we want to check all register values (!clrstack can also show you these, using the parameter –R), we can use windbg windows in VIEW Menu like (Locals, Registry, …). Also I like to have the un assembly window open so that I can step-by-step (visually, because you can use t and p to step into or step over). Register window will show in red what has changed.

    In my sample I will step into this method using windbg icons

    untitled

    If we already know what our final destination is (step-by-step I described just above is very useful when trying to understand how something works), we can take some shortcuts and use Reflector to dig and find our stop.

    In my sample, i want to set a breakpoint in System.WorkflowServices.dll in

    private void InitializeDescription(WorkflowDefinitionContext workflowDefinitionContext, UriSchemeKeyedCollection baseAddresses)

    So, i´m going to use !bpmd like before

    0:003> !bpmd System.WorkflowServices.dll System.ServiceModel.WorkflowServiceHost.InitializeDescription
    Found 1 methods...
    MethodDesc = 000007fee5cb32e8
    Setting breakpoint: bp 000007FEE5DA4070 [System.ServiceModel.WorkflowServiceHost.InitializeDescription(System.Workflow.Runtime.WorkflowDefinitionContext, System.ServiceModel.UriSchemeKeyedCollection)]

    Press g

    0:003> g
    ModLoad: 000007fe`ed980000 000007fe`ed9d9000   C:\Windows\assembly\NativeImages_v2.0.50727_64\SMDiagnostics\98ef29a4dddcc3de6a1510907db4a165\SMDiagnostics.ni.dll
    ModLoad: 000007fe`e4980000 000007fe`e4ac3000   C:\Windows\assembly\NativeImages_v2.0.50727_64\System.Configuration\1df55745d2cb08fa7a01af7382f81d50\System.Configuration.ni.dll
    ModLoad: 000007fe`ef920000 000007fe`effc4000   C:\Windows\assembly\NativeImages_v2.0.50727_64\System.Xml\e185ca4d880a9803d1c8aecba9045b14\System.Xml.ni.dll
    Breakpoint 0 hit
    System_WorkflowServices_ni!System.ServiceModel.WorkflowServiceHost.InitializeDescription(System.Workflow.Runtime.WorkflowDefinitionContext, System.ServiceModel.UriSchemeKeyedCollection):
    000007fe`e5da4070 53              push    rbx

    So, i have reached InitializeDescription. When troubleshooting a badboy that changes a variable that shouldn´t or i´m just trying to get more details I look at what is on my stack. And for that we can use !dso (DumpStackObjects)

    TIP: registry window show in red, values that have changed when doing step-by-step.

    So imagine you are interested on WorkflowDefinitionContext parameter above. After our breakpoint being hit I will use !dso

    0:000> !dso
    OS Thread Id: 0x15cc (0)
    RSP/REG          Object           Name
    rbx              00000000025b4bd0 System.ServiceModel.UriSchemeKeyedCollection
    rcx              0000000002587520 System.ServiceModel.WorkflowServiceHost
    rdx              0000000002587608 System.Workflow.Runtime.CompiledWorkflowDefinitionContext
    rsi              0000000002587520 System.ServiceModel.WorkflowServiceHost
    rdi              0000000002587608 System.Workflow.Runtime.CompiledWorkflowDefinitionContext
    rbp              0000000002587500 System.Object[]
    r8               00000000025b4bd0 System.ServiceModel.UriSchemeKeyedCollection
    00000000001dea90 0000000002587520 System.ServiceModel.WorkflowServiceHost
    00000000001dea98 0000000002587608 System.Workflow.Runtime.CompiledWorkflowDefinitionContext
    00000000001deaa0 00000000025b4bd0 System.ServiceModel.UriSchemeKeyedCollection
    00000000001dead0 0000000002587500 System.Object[]    (System.Uri[])
    00000000001deae0 0000000002587520 System.ServiceModel.WorkflowServiceHost
    00000000001deae8 00000000025874d8 System.RuntimeType
    00000000001deaf0 0000000002587500 System.Object[]    (System.Uri[])
    00000000001deb28 0000000002581308 System.String
    00000000001deb30 00000000025874d8 System.RuntimeType
    00000000001deb38 0000000002587520 System.ServiceModel.WorkflowServiceHost
    00000000001deba0 0000000002583808 System.Object[]    (System.String[])
    00000000001ded28 0000000002583808 System.Object[]    (System.String[])
    00000000001def10 0000000002583808 System.Object[]    (System.String[])
    00000000001def38 0000000002583808 System.Object[]    (System.String[])

    As you can see above in black (object address) and in green (object i´m interested on). Now we just use !do (DumpObject) to look inside objects we are interested on.

    0:000> !do 0000000002587608
    Name: System.Workflow.Runtime.CompiledWorkflowDefinitionContext
    MethodTable: 000007fee5de2420
    EEClass: 000007fee5c9ec20
    Size: 40(0x28) bytes
    (C:\Windows\assembly\GAC_MSIL\System.WorkflowServices\3.5.0.0__31bf3856ad364e35\System.WorkflowServices.dll)
    Fields:
                  MT    Field   Offset                 Type VT     Attr            Value Name
    0000000000000000  40001e2        8                       0 instance 0000000000000000 workflowRuntime
    000007fee4c1e3d8  40001e4       10 ...entModel.Activity  0 instance 0000000000000000 rootActivity
    000007fef33209b8  40001e5       18          System.Type  0 instance 00000000025874d8 workflowType
    000007fef33209b8  40001e3      290          System.Type  0   static 0000000002587630 activityType

    Now, let’s take some more steps and go to Reflector. Below is InitializeDescription code

    protected void InitializeDescription(UriSchemeKeyedCollection
    baseAddresses)
    {
        foreach (Uri uri in baseAddresses)
        {
            this.baseAddresses.Add(uri);
        }
        IDictionary<string, ContractDescription> implementedContracts = null;
        ServiceDescription description = this.CreateDescription(out implementedContracts);
        this.description = description;
        this.implementedContracts = implementedContracts;
        this.ApplyConfiguration();
        this.initializeDescriptionHasFinished = true;

    (…)

     

    Let’s suppose we want to see what those URI are (imagine that the only way to find was to step into the foreach). Here we would take the same approach by looking at the method assembly (u) and then use BP to set breakpoint on that line.

    I know it might look a bit confusing, but try with some simple samples just to get to know the commands. Also be patient when trying to understand what´s going on inside because sometimes it´s not simple and it requires restarting over and over, long hours but in the end I find it very rewarding.

    Till next time.
    Bruno

    Posted by ptadcs | 2 Comments
    Filed under:

    Yet another Death by the ViewState – Part II

    It´s been a while since my post on ViewState. This is just a update about the article i mention that everyone should read to truly understand what viewstate is all about.

    http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx

     

    Have fun,

    Bruno

    Posted by ptadcs | 1 Comments

    Silverlight Concepts Samples

    Yesterday I made a presentation entitled “Best Practices in Silverlight 2 (Intro)” where I showed several small samples to illustrate the concepts I wished to expose. Some listeners asked me about the samples source code and I agreed to publish it. You can find it on this post.

    Please notice this code was developed to illustrate some concepts during the session and may not make sense when analyzed out of context.

    I might write a post explaining some of the concepts later on.

    Project Name: PFCoverflow
    Description: My “Cover-flow alike” UI implementation. Please read part I and part II.
    Source Code: here.
    Running Sample: here.

    Project Name: MySamples… (all other)
    Source Code: here.

    Detail:

    Project Name: MySamples.InstallWithout vs MySamples.InstallCustom
    Description: Customizing Installation Experience


    Project Name: MySamples.SplashScreenWithout vs MySamples.SplashScreen
    Description: Customizing Load Experience


    Project Name: MySamples.RedrawRegions
    Description: Playing with parameters


    Project Name: MySamples.SplashScreenAsyncLoad
    Description: Async Loading Resources


    Project Name: MySamples.IsolatedStorage
    Description: Using Isolated Storage


    Project Name: MySamples.DesignMode
    Description: Data on UserControls in DesignMode


    Project Name: MySamples.Text
    Description: Scaling Text (to measure performance)


    Project Name: MySamples.Memory
    Description: Garbage Collector Test


    Project Name: MySamples.Localization
    Description: Localizing User Controls with Resource Files

    Pedro Fortes

    Posted by ptadcs | 0 Comments
    Filed under:

    Adapting SQLDiag to your needs

    Often times, our team is confronted with SQL Server performance issues and in most of those times, the issues are due to locking and blocking in heavily loaded scenarios. As such, our typical approach consists in gathering a SQL Server Profiler trace while running a script which periodically polls the database for blocked SPIDs. The combined output of these tools usually allows us to pinpoint the statements accountable for those phenomena.

     

    If you haven’t heard of such a script, you’ll find it in a Microsoft Support Knowledge Base article named How to monitor blocking in SQL Server 2005 and in SQL Server 2000, along with the instructions on how to collect information from it.

     

    Recently, in response to one of these such problems, I decided to give SQLDiag a chance. By default, it gathers a lot of valuable information and all one needs to do is just to start it from a command prompt by giving it a couple of arguments. One of those arguments allows you to choose a template for data gathering, in which you specify which performance counters to include, which profiler events, whether to export the Event Viewer logs or not, and so on. In summary: great stuff!!

     

    Before getting deep into those templates, I pinged Bruno, as solving-SQL-Server-performance-issues is his middle name, and asked him if he had any finely crafted templates ready to use anywhere. His answer didn’t surprise me: “I’m kind of old-school… I get a Profiler trace and the blocking script output”. Well, if that’s exactly what we need, why mess around with performance counters, MSDiag and event viewer logs? He’s absolutely right and that is the reason why I didn’t give SQLDiag such a chance before.

     

    Still, however, I decided to run that extra mile and have SQLDiag gather those two, while saving us the time to configure the trace, locate the looping script and issue an osql command. As you probably know, SQLDiag already allows you to gather some blocking data, but notably not as much as you’d get from sp_blocker_pss80.

     

    Of course, there are other modern approaches you might want to consider, such as those described in:

    If you’re still following, then you’re probably old school as well as Bruno and me, and so let me move on to what to do if you’d like to use SQLDiag as your new starting point for your good old troubleshooting methodology:

    • First, ensure the sp_blocker_pss80 stored procedure is available in the server, according to the 271509 article;
    • Locate the sqldiag.exe utility. The quickest way for me was opening a command prompt and issuing the command where sqldiag
      where sqldiag

    • Also, according to the article above, create a checkblb.sql file in the same directory in which SQLDiag resides. Here’s my version of that file:

      WHILE 1=1
      BEGIN
         EXEC master.dbo.sp_blocker_pss80
         WAITFOR DELAY '00:00:10'
      END
      GO

    • Create a new and specially crafted template in which you include the SQL Server Profiler events you usually need, and add the custom task which starts the sp_blocker_pss80-based blocking script data gathering. Here’s my personal template flavor (I've highlighted the specifics:

      <?xml version="1.0" standalone="yes"?>
      <
      dsConfig 
       
      xmlns:pssd="http://tempuri.org"
       
      xmlns:xsi=
      http://www.w3.org/2001/XMLSchema-instance
        xsi:noNamespaceSchemaLocation="SQLDiag_Schema.Xsd">
        <
      Collection setupver="3.0.1.7" casenumber="SRX000000000000">
          <
      Machines>
            <
      Machine name=".">
               <
      MachineCollectors>
                 <
      EventlogCollector enabled="false" startup="false" shutdown="true" />
                 <
      PerfmonCollector enabled="false" pollinginterval="5" maxfilesize="256">
                   <
      PerfmonCounters>
                     <
      PerfmonObject name="\MSSQL$%s:General Statistics" enabled="true">
                       <
      PerfmonCounter name="\User Connections" enabled="true" />
                     </
      PerfmonObject>
                   </
      PerfmonCounters>
                 </
      PerfmonCollector>
               </
      MachineCollectors>
               <
      Instances>
                 <
      Instance name="*" windowsauth="false" ssver="9" user="sa">
                   <
      Collectors>
                     <
      SqldiagCollector enabled="true" startup="false" shutdown="true" />
                     <
      BlockingCollector enabled="true" pollinginterval="5" maxfilesize="350"/>
                     <
      ProfilerCollector enabled="true" template="_GeneralPerformance90.xml" pollinginterval="5" maxfilesize="350">
                       <
      Events>
                         <
      EventType name="Errors and Warnings">
                           <
      Event id="137" name="Blocked Process Report"  enabled="true"  />
                           <
      Event id="22" name="ErrorLog"  enabled="true" />
                           <
      Event id="21" name="EventLog"  enabled="true" />
                           <
      Event id="33" name="Exception"  enabled="true" />
                         </
      EventType>
                         <
      EventType name="Locks">
                           <
      Event id="148" name="Deadlock Graph"  enabled="true" />
                           <
      Event id="25" name="Lock:Deadlock"  enabled="true" />
                           <
      Event id="59" name="Lock:Deadlock Chain"  enabled="true" />
                           <
      Event id="60" name="Lock:Escalation"  enabled="true" />
                           <
      Event id="189" name="Lock:Timeout (timeout &gt; 0)" enabled="true" />
                         </
      EventType>
                         <
      EventType name="OLEDB">
                           <
      Event id="61" name="OLEDB Errors"  enabled="true" />
                         </
      EventType>
                         <
      EventType name="Sessions" enabled="true">
                           <
      Event id="17" name="ExistingConnection"  enabled="true" />
                         </
      EventType>
                         <
      EventType name="Stored Procedures">
                           <
      Event id="10" name="RPC:Completed"  enabled="true" />
                           <
      Event id="11" name="RPC:Starting"  enabled="true" />
                           <
      Event id="43" name="SP:Completed"  enabled="true" />
                           <
      Event id="42" name="SP:Starting"  enabled="true" />
                           <
      Event id="45" name="SP:StmtCompleted"  enabled="true" />
                           <
      Event id="44" name="SP:StmtStarting"  enabled="true" />
                         </
      EventType>
                         <
      EventType name="TSQL">
                          <
      Event id="12" name="SQL:BatchCompleted"  enabled="true" />
                           <
      Event id="13" name="SQL:BatchStarting"  enabled="true" />
                           <
      Event id="40" name="SQL:StmtStarting"  enabled="true" />
                           <
      Event id="41" name="SQL:StmtCompleted"  enabled="true" />
                         </
      EventType>
                         <
      EventType name="Transactions">
                           <
      Event id="19" name="DTCTransaction"  enabled="true" />
                           <
      Event id="50" name="SQL Transaction"  enabled="true" />
                         </
      EventType>
                       </
      Events>
                     </
      ProfilerCollector>
                     <
      CustomDiagnostics>
                       <
      CustomGroup name="sp_blocker_pss80" enabled="true" />
                       <
      CustomTask enabled="true"
                                  
      groupname="sp_blocker_pss80"
                                  
      taskname="Gather the sp_blocker_pss80 output"
                                  
      type="Utility"
                                   
      point="Startup"
                                  
      wait="No"
                                  
      cmd="osql -E -S%server_instance% -icheckblk.sql -o&quot;%output_path%sp_blocker_pss80.out&quot; -w2000" />
                     </
      CustomDiagnostics>
                   </
      Collectors>
                 </
      Instance>
               </
      Instances>
             </
      Machine>
           </
      Machines>
        </
      Collection>
        <
      Analysis>
          <
      Producers>
            <
      Producer name="System Info Loader" assembly="BCPLoader.dll" selected="false" />
            <
      Producer name="Blocker Loader" assembly="TextRowsetLoader.dll" selected="false" />
            <
      Producer name="Event Log Loader" assembly="BCPLoader.dll" selected="false" />
            <
      Producer name="SQLDiag Loader" assembly="TextRowsetLoader.dll" selected="false" />
          </
      Producers>
          <
      Analyzers>
            <
      Analyzer name="SQLDiag Analyzer" assembly="BaseAnalyzer.dll" selected="true" />
            <
      Analyzer name="Waitstats Analyzer" assembly="BaseAnalyzer.dll" selected="true" />
            <
      Analyzer name="Corruption Root Cause Analyzer" assembly="HardwareAnalyzer.dll" selected="true" />
            <
      Analyzer name="Blocker Analyzer" assembly="BlockerAnalyzer.dll" selected="true" />
            <
      Analyzer name="Perfmon Analyzer" assembly="BaseAnalyzer.dll" selected="false" />
          </
      Analyzers>
          <
      ViewItems>
          </
      ViewItems>
          <
      Trends>
          </
      Trends>
        </
      Analysis>
      </
      dsConfig>
    • Run SQLDiag making sure you’re giving it the right template with the /I parameter.
    • Finally, go figure out whether you should stick with the old school method, or let SQL Server give you what you need with Dynamic Management Views and stuff alike. That’s precisely what I’ll be doing next. :-)

    Oh, don’t mind the level of detail under PerfmonCollector even if it’s disabled. Take a look at the schema in SQLDiag_Schema.XSD and you’ll see why these have to be added no matter whether the whole section is disabled. The alternative, changing the schema itself, might not be a good idea as we do not know how the underlying SQLDiag code interprets the template files and that’s exactly what a schema is for: enforcing a common structure for these files, right?

     

    Well, that’s all for now. Have fun and till next time,

       Manuel Oliveira

    Making Dependency Injection your friend

     

    Imagine…You are happily in the final steps of your project, and suddenly the client “decides” that the logging mechanism that you development in your Solution does not met the requirements of their processes, instead of the good old Enterprise Library Logging that you had used, they want that the Solution use a different mechanism that they use in other Solutions…Wouldn’t be nice if we can just say to our Solution to use a new Logging Mechanism without changing our code.

     

    Imagine….You need the replicate your Production Environment in a VPC Image to promote some kind of Test or demonstration, after you start installing your Platform in the Virtual Environment you realize you going to need a DC Server, an Active directory, etc…Wouldn’t be nice if you can just say to your solution to use a new Authentication Mechanism instead of the Integrated one used in our Production Environment, and doing that without have to change our code.

     

    Been there? Sure you had. I know I had. And the solution for this, is Dependency Injection, I’m telling you.

     

    So let’s talk a little bit about this DI thing.

     

    In nowadays everyone recognize the benefits of using an approach that promotes two things:

    ·         Loose coupling between Components

    ·         High level of cohesion of the Solution.

     

    One of the mechanisms that are a potential champion in this area is the Dependency Injection paradigm. With this kind of Model the teams are able to promote aggressive decoupling and independence of the components of their Solutions

     

    Of course we all are aware of things like: Spring .NET, CASTLE Windsor or even the classic Struture Map.

     

    But we all also know that this are lightweight dependency Injection Containers that can give us great help in assembling our components from different projects in a application with great levels of cohesion in run time, also they are very useful in promoting the reusability of the code that the Teams producing, but still give us little power and flexibility to satisfy our real needs.

     

    The Dependency Injection, in the other side, is one of those mechanisms that give us the power to create all the stuff we need in a very comprehensive and easy way. You can find a very old but still very actual introduction to the Dependency Injection technique by Martin Fowler in this article, go read (a classic).

     

    In an essence the DI gives to the developers the ability to decouple related but distinct operations in client applications. This implies that it is easier for the developer to focus on create smaller building blocks that potentiate the degrees of reusability of their code.

     

    However this kind of technique, or even the related Inversion of Control (IOC) approach, are not very widely adopted because the developers tend to think that this approaches are only useful on an context of Unit Testing.

     

    Typically, if the developers have not adopt a TDD approach, they will not take time to considering this Design Alternatives, so they are far from getting the big advantages that are inherent to the DI and IOC.

     

    So, what advantages I am talking about? We can discuss a lot around this issue, but I think I can enumerate at least the following, without getting wrong:

     

     

    ·         Dynamic and pluggable Architectures

    ·         Dependency Injection

    ·         Dynamic and pluggable architectures

    ·         Consistent (and by design) Extensibility

    ·         Interception allowance

    ·         Lifecycle Management

    ·         Independent component evolution

    ·         Decoupled Architectures

    ·         Separation of concerns

    ·         Business Logic versus Infrastructure Logic

     

    Regarding the possible approaches to use the DI, depending what you need, you can use the following:

    ·         Constructor Injection

     

     

     

     

    ·         Setter Injection

     

     

     

    ·         Interface Injection

     

     

     

     

    In one of the Projects that I had been involved I can say that the use of the DI clearly save our day. Let’s say we had a solution ready to be delivered and suddenly in last minute the client decides that they don’t want anymore that we use the logging mechanisms from the Enterprise Library that we had been using in our solution, instead they want the use an internal mechanism they use in all their applications, sounds familiar?

    Well don’t worry, here comes the DI to save the day, because we had use DI exhaustively in our Project, inclusive in the Logging Classes, we are able to change the Logger without need to change any line of our code.

    Let’s see that, in just a brief overview:

    We had use for the Logging mechanisms of our solution the DI Constructor approach, so, we had configured the dependency in our Logger something like the follow:

    public class LoggerSvc()

    {

                    public void MyMethod1(Logger logDef)

                    {

                                   IDependencyContainer container = DependencyContainerProvider.GetContainer();

                                   container.Register<ILoggerWriter, MyLoggerWriter>();

                                   LoggerManager manager = container.Resolve<LoggerManager>();

                                   manager.AddLogger(logDef);

                    }

                   

                    //other code goes here

    }

    DefaultMappingAttribute

    [DefaultMapping(typeof(MyLoggerWriter))]

    public interface ILoggerWriter()

    {              //interface code goes here}

    public class LoggerSvc()

    {

                    public void MyMethod1(Logger logDef)

                    {

                                   IDependencyContainer container = DependencyContainerProvider.GetContainer();

                                   TransactionManager manager = container.Resolve<LoggerManager>();

                                   manager.AddLogger(logDef);

                    }

                    //other code goes here

    }

     

    After this, we had to implement the Constructor Injection:

     

    public class LoggerManager()

    {

                    public LoggerManager

                    (ILoggerWriter writer)

                    {

                                   this.LoggerWriter = writer;

                    }

                    public ILoggerWriter LoggerWriter {get; private set;}

                   

                    //other code goes here

    }

     

    Et voila, when we receive the new “requirement” from the client we had the capability to just promote the use of the new Logger by a simple change in our configuration file by using the Policy Injection Application Block (PIA).

    For those who are not aware of this “wonder”, I strongly recommend that you go find out more about, but I can say that it is a powerful mechanism that gives us a common behavior injection mechanism and a clear extensibility point for every one of our solutions:

    In a visual way it is something like this.

     

     

     

    Finally some tips to implement a good DI approach

    ·         Make all classes inherent from a single base, so that they can be easily managed by container;

    ·         Make the framework as simple as possible, put main functionalities into plug-ins, so that sub-components can be easily replaced;

    ·         Use the injection methods and service locator together; (e.g., Use constructor injection to inject service locator)

    So, farewell and remember, SGIP!

    JPauloP

    Posted by ptadcs | 0 Comments

    Silverlight and "Cover Flow" – Part II

    In my last post I talked about the difficulty of implementing a “vanishing point” perspective effect with Silverlight since (currently) it only supports 2D affine transforms.
    As a result, most of “Cover Flow” implementations with Silverlight “avoided” perspective.
    However, my belief is that if we do that we’ll significantly diminish the Coverflow interface perceptive quality.

    How can we then implement such interface, without building a whole 3D engine, and just using the Silverlight affine transforms?

    - It can be done with Polygon triangulation and Texture mapping.

    If we decompose the polygons (cover artwork in our case) into a set of triangles, and then linearly interpolate its content in accordance with its vertices, we are still using an affine transform and the result is close to a true perspective transform.


    (You can obtain a great Textured Triangle Control for Silverlight 2 by Florian Kruesch here).

    There’s a catch, however. Because affine texture mapping does not take into account the polygon's vertices depth information it will not look exactly right and we’ll see a noticeable defect. The only way to get around this is by adding more, and smaller, triangles.


    But what about the Coverflow interface, how can this affect it visually?
    Well, I built one and you can see (and hear) it yourself here.

    See you.
    Pedro Fortes

    Update (2009-02-19): Source code now available here.

    Posted by ptadcs | 5 Comments
    Filed under:

    Attachment(s): PFCoverflow 20090119a public.zip
    More Posts Next page »
     
    Page view tracker