WTF Next?

Dev ramblings from a master of nothing.

  Home  |   Contact  |   Syndication    |   Login
  125 Posts | 0 Stories | 74 Comments | 0 Trackbacks

News

INETA Community Speakers Program
GeeksWithBlogs.net: WTFNext's hosting!

View Stacy Vicknair's profile on LinkedIn

Twitter







Tag Cloud


Archives

Post Categories

Community Links

User Groups

Monday, November 28, 2011 #

As an individual who does not use Internet Explorer as their primary browser, there is a great feature that you may never notice that allows you to easily copy files to and from a document library: the Open in Windows Explorer link. In browsers such as Chrome or Firefox this link may not appear.

I know this isn’t a major groundbreaking feature, but it’s really easy to overlook and it’s worth knowing about, especially when you need to create a local copy of a full document library. In this quick blog we’ll go over how to access this feature in both SharePoint 2007 and 2010.

First, make sure you are in Internet Explorer. These options may not show in other browsers.

In SharePoint 2007, browse to the document library you would like to access then select Actions > Open with Windows Explorer.

image

In SharePoint 2010, browse to the document library you would like to access then select Library Tools > Library > Open with Explorer from the ribbon.

image

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, October 25, 2011 #

If you, like me, have ever looked over the MSDN documentation and though how nice it would be to have that type of documentation for your codebase, SandCastle is the tool you’ve been looking for. SandCastle is a Codeplex project initiated by Microsoft in order to provide MSDN-esque documentation for .NET projects or asssemblies. The documentation can come in several formats such as CHM files or a website.

 

GhostDoc and SandCastle Help File Builder

To get started with SandCastle for documentation, I recommend a few additional tools: GhostDoc and SandCastle Help File Builder.

GhostDoc is a Visual Studio extension that allows quick XML documentation to be generated based on naming convention for methods, properties and parameters. XML documentation is the heart of how SandCastle generates documentation, so being able to quickly generate simple comments is a great benefit. The Pro version of GhostDoc also allows for customizations based on T4 templating.

SandCastle Help File Builder is a second Codeplex project that adds a GUI and additional support for SandCastle to make the overall experience of its use even better.

 

Installation

For a comprehensive installation guide, check out the SandCastle Help File Builder Installation Instructions. Their guided installer is easy to use and will verify that everything you need is in the right place. It will also let you know if you are lacking any dependencies you might need for generating specific help file types.

 

Usage

Once you have SHFB installed, open the SandCastle Help File Builder GUI and select File > New Project… then choose a location and name for your project. I follow the conventions for project naming that we use for any other project type and add the project to a subdirectory of the code solution.

image

SHFB saves projects as shfbproj types. These types can be built using MSBuild and incorporated into your current build processes. Do note that the time to generate documentation has a fair amount of overhead to reflect through your generated code.

After you have saved your project you can proceed to customize the sources to document by right clicking Documentation Sources then browsing to either the solution, project, or dll file you would like to include.

SS-2011-10-25_19.58.35

If you are looking to generate an HTML site specifically, this can be set on the HelpFileFormat under the Build section of the project properties.

SS-2011-10-25_20.04.16

Afterwards, just select Documentation > Build Project to create your very own MSDN-esque documentation!

SS-2011-10-25_20.09.45

 

Links

http://sandcastle.codeplex.com
http://shfb.codeplex.com/
http://submain.com/products/ghostdoc.aspx
http://www.ewoodruff.us/shfbdocs/Index.aspx?topic=html/8c0c97d0-c968-4c15-9fe9-e8f3a443c50a.htm
http://broadcast.oreilly.com/2010/09/build-html-documentation-for-y.html

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Sunday, October 09, 2011 #

Test Data Builder Pattern

When unit testing we often need to fill any POCO objects with enough data to satisfy the needs of the test. Redoing this in every test can quickly become a burden and slow down the testing process. Test Data Builder is a pattern that’s meant to help in just that situation.

With test data builder you build a fluent interface that allows you to build out your POCO objects by only replacing the properties that you need specific values for. The other values are set to defaults specified by the builder.

Here’s a classic example of test data builder:

Our POCO Object

   1: Public Class Person
   2:     Public Property FirstName As String
   3:     Public Property LastName As String
   4:     Public Property DateOfBirth As DateTime
   5: End Class

Our Test Data Builder Class

   1: Public Class PersonBuilder
   2:     'Set the defaults
   3:     Private _firstName As String = "Default"
   4:     Private _lastName As String = "Default"
   5:     Private _dateOfBirth As DateTime = New DateTime(1999, 12, 31)
   6:  
   7:     Public Function WithFirstName(ByVal firstName As String) As PersonBuilder
   8:         _firstName = firstName
   9:         Return Me
  10:     End Function
  11:  
  12:     Public Function WithLastName(ByVal lastName As String) As PersonBuilder
  13:         _lastName = lastName
  14:         Return Me
  15:     End Function
  16:  
  17:     Public Function WithDateOfBirth(ByVal dateOfBirth As DateTime) As PersonBuilder
  18:         _dateOfBirth = dateOfBirth
  19:         Return Me
  20:     End Function
  21:  
  22:     Public Function Build() As Person
  23:         Return New Person() With
  24:             {
  25:                 .FirstName = _firstName,
  26:                 .LastName = _lastName,
  27:                 .DateOfBirth = _dateOfBirth
  28:             }
  29:     End Function
  30: End Class

Usage example

   1: Dim person = New PersonBuilder() _
   2:     .WithFirstName("Stacy") _
   3:     .WithDateOfBirth(New DateTime(1984, 12, 6)) _
   4:     .Build()

Still a lot of work

Depending on how many objects you need to create builders for and how many properties each object has you can still be in for a lot of upfront work following the test data builder pattern to create that fluent experience.

 

Creating the builder pattern with object initializers

In .NET we have object initializers that can take much of this extra work out by providing an expressive method of setting the object properties. If possible, simply subclassing off of the POCO will prevent us from even needing to write out all of the properties, then we can set default values in the constructor.

Our Subclassed Test Data Builder

   1: Public Class PersonBuilderWithObjectInitializers
   2:     Inherits Person
   3:  
   4:     Public Sub New()
   5:         FirstName = "Default"
   6:         LastName = "Default"
   7:         DateOfBirth = New DateTime(1999, 12, 31)
   8:     End Sub
   9:  
  10:     Public Function Build() As Person
  11:         Return New Person() With
  12:             {
  13:                 .FirstName = FirstName,
  14:                 .LastName = LastName,
  15:                 .DateOfBirth = DateOfBirth
  16:             }
  17:     End Function
  18: End Class

The new builder’s usage

   1: Dim person = New PersonBuilderWithObjectInitializers() With
   2:         {
   3:             .FirstName = "Stacy",
   4:             .DateOfBirth = New DateTime(1984, 12, 6)
   5:         }.Build()

Why still have a build method?

Some of you might be asking, “Why keep the build method when polymorphism should do the work?” Well, good point. The reason I keep the build method is that when working against Entity Framework against POCO objects it will attempt to figure out the true type of the object, not just the type the object is cast as. As a result, it will complain when trying to persist the object. The build method in this case just acts as added assurance that if any type discovery is called against the object you will be safe knowing that the correct type will be discovered.

 

C# examples

Our POCO Object

   1: public class Person
   2: {
   3:     public string FirstName { get; set; }
   4:     public string LastName { get; set; }
   5:     public DateTime DateOfBirth { get; set; }
   6: }

Our Test Data Builder Class

   1: public class PersonBuilder
   2: {
   3:     // Set our defaults
   4:     private string _firstName = "Default";
   5:     private string _lastName = "Default";
   6:     private DateTime _dateOfBirth = new DateTime(1999, 12, 31);
   7:  
   8:     public PersonBuilder WithFirstName(string firstName)
   9:     {
  10:         _firstName = firstName;
  11:         return this;
  12:     }
  13:  
  14:     public PersonBuilder WithLastName(string lastName)
  15:     {
  16:         _lastName = lastName;
  17:         return this;
  18:     }
  19:  
  20:     public PersonBuilder WithDateOfBirth(DateTime dateOfBirth)
  21:     {
  22:         _dateOfBirth = dateOfBirth;
  23:         return this;
  24:     }
  25:  
  26:     public Person Build()
  27:     {
  28:         return new Person
  29:                    {
  30:                        FirstName = _firstName,
  31:                        LastName = _lastName,
  32:                        DateOfBirth = _dateOfBirth
  33:                    };
  34:     }
  35: }

Usage example

   1: //arrange
   2: var person = new PersonBuilder()
   3:     .WithFirstName("Stacy")
   4:     .WithDateOfBirth(new DateTime(1984, 12, 6))
   5:     .Build();

Our Subclassed Test Data Builder

   1: public class PersonBuilderWithObjectInitializers : Person
   2: {
   3:     public PersonBuilderWithObjectInitializers()
   4:     {
   5:         // Set our defaults
   6:         FirstName = "Default";
   7:         LastName = "Default";
   8:         DateOfBirth = new DateTime(1999, 12, 31);
   9:     }
  10:  
  11:     public Person Build()
  12:     {
  13:         return new Person
  14:             {
  15:                 FirstName = FirstName,
  16:                 LastName = LastName,
  17:                 DateOfBirth = DateOfBirth
  18:             };
  19:     }
  20: }

The new builder’s usage

   1: var person = new PersonBuilderWithObjectInitializers
   2:                 {
   3:                     FirstName = "Stacy",
   4:                     DateOfBirth = new DateTime(1984, 12, 6)
   5:                 }.Build();
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, September 29, 2011 #

When we talk about UI Architecture, a common theme of Model-View-Something continues to come up. The question is, however, what is the something? Am I working with Model-View-Controller? Model-View-Presenter? Something else?

The purpose of this blog is to explore the difference between MVC / MVP to give you an understanding of what they mean to accomplish, what are the differences and what situations best cater to each.

 

Does it really matter?

Does the difference really matter between MVC / MVP? Well, in purpose it hardly does. When we implement MVC / MVP we have the same goal: separation of presentation from the data model and synchronization of data between the model and the view. These goals are achieved by both patterns.

In implementation there is a slight difference.

 

Model-View-Controller

The MVC pattern originated in a time where every individual element of a display was managed by custom code. The view was literally the rendered representation of the model and the controller handled the inputs from the user to interact with the model. The model would then inform any concerned views or controllers via the observer pattern. Naturally, MVC lends itself to the situations where the interactions of the user are immediately translated into actions against the controller.

In .NET the ASP.NET MVC framework caters best towards MVC. With ASP.NET MVC the application receives a request for a specific URL. The URL is interpreted to determine a specific Action associated with a specific Controller. The Controller executes the action then returns a View that renders a representation of the model.

 

Model-View-Presenter

MVP was introduced alongside the concept of “widgets” or the more familiar notion of controls. Like the controls we use today in WebForms and WinForms, these early “widgets” were capable of understanding the user input on their own and delegating events as they arise. As a result, in the “widget” space our actions are translated into events that happen on the View itself that must be passed along, rather than handled immediately by the controller. As a result, Views have a tighter coupling to a specific Presenter because of the need to delegate information. This usually lends towards a one-to-one relationship of Presenters and Views.

The presenter in MVP also takes a more “hands on” approach than with MVC’s controller. Usually the presenter will have access to manipulate the view rather than the view talking directly to the model. This leads to the tighter coupling between the presenter and the view in MVP as opposed to MVC, but an interface is usually used as a layer of separation.

As with its origin MVP caters towards the .NET platforms that support built-in controls. This includes both ASP.NET WebForms and WinForms.

 

That’s all, right?

What I hope you’ve gained from this blog is enough to identify the goals and slight differences between MVC and MVP as well as the areas in .NET development where they apply. Check out the references below for a little more information about each and their differences!

References:
http://www.codinghorror.com/blog/2008/05/understanding-model-view-controller.html
http://heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html
http://martinfowler.com/eaaDev/uiArchs.html
http://haacked.com/archive/2008/06/16/everything-you-wanted-to-know-about-mvc-and-mvp-but.aspx

Technorati Tags: ,,,
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, August 23, 2011 #

When testing in ASP.NET MVC3, one of the common elements you might want to test is authorization. Although the framework does most of the heavy lifting for ASP.NET Membership and authorization it is still worthwhile to be able to write a test to show that the proper Authorization tag is in place.

You might think that it’s as easy as calling the method on the controller with a proper context, but that’s not the case. When you call the methods directly on the controller the authorizations are skipped. These authorizations are handled by the ActionInvoker when the MVC application runs, so in order to test this via MVC itself would take a lot of cruft. Since we trust that ASP.NET MVC is doing its job correctly it is easier to simply test for the presence of the attributes.

Since this is such a common task I ventured forth to create an extension method that will accomplish exactly what I want with the API I want. Using a lambda syntax most of us are familiar with from mocking frameworks, the final product yields a test method like the following:

   1: <TestMethod()>
   2: Public Sub Register_WhenUserIsInAdministratorRole_ShouldBeAuthorized()
   3:     'Arrange
   4:     Dim target = New AccountController()
   5:  
   6:     'Assert
   7:     target.AssertRoleIsAuthorizedForAction(Sub(a) a.Register(New RegisterModel()), "Administrator")
   8: End Sub

 

Simply pass in a lambda of the action you are attempting to test along with the role you expect authorization to be successful for. The extension method code is as follows:

   1: <Extension()>
   2: Public Sub AssertRoleIsAuthorizedForAction(Of T As Controller)(ByVal controller As T,
   3:     ByVal expression As Expression(Of Action(Of T)), role As String)
   4:  
   5:     'Arrange
   6:     'Get method from expression
   7:     Dim callExpression = TryCast(expression.Body, MethodCallExpression)
   8:     If callExpression Is Nothing Then
   9:         Throw New ArgumentException("Could not determine method from expression", "expression")
  10:     End If
  11:  
  12:     'Act
  13:     Dim roles = callExpression.Method.GetCustomAttributes(GetType(AuthorizeAttribute), inherit:=True) _
  14:         .Cast(Of AuthorizeAttribute)() _
  15:         .Where(Function(a) Not String.IsNullOrEmpty(a.Roles)) _
  16:         .SelectMany(Function(a) a.Roles.Split(",")) _
  17:         .ToList()
  18:  
  19:     'Assert
  20:     Assert.IsTrue(roles.Contains(role))
  21: End Sub

The method takes the given lambda and extracts the method. Then the AuthorizeAttributes for the method that include roles are split into a list of roles. Finally we assert that the list of roles contains our role in question.

In C#:

   1: [TestMethod]
   2: public void Register_WhenUserIsInAdministratorRole_ShouldBeAuthorized()
   3: {
   4:     //arrange
   5:     var accountController = new AccountController();
   6:  
   7:     //assert
   8:     accountController.AssertRoleIsAuthorizedForAction(ac => ac.Register(new RegisterModel()), "Administrator");
   9: }
   1: public static void AssertRoleIsAuthorizedForAction<T>(this T controller, 
   2:     Expression<Action<T>> expression, string role) where T : Controller
   3: {
   4:     //Arrange
   5:     //Get method from expression
   6:     var callExpression = expression.Body as MethodCallExpression;
   7:     if(callExpression == null)
   8:         throw new ArgumentException("Could not determine method from expression", "expression");
   9:  
  10:     //Act
  11:     var roles = callExpression.Method.GetCustomAttributes(typeof(AuthorizeAttribute),true)
  12:         .Cast<AuthorizeAttribute>()
  13:         .Where(a => !string.IsNullOrEmpty(a.Roles))
  14:         .SelectMany(a => a.Roles.Split(','))
  15:         .ToList();
  16:  
  17:     //Assert
  18:     Assert.IsTrue(roles.Contains(role));
  19: }

 

References:
http://stackoverflow.com/questions/669175/unit-testing-asp-net-mvc-authorize-attribute-to-verify-redirect-to-login-page
http://darioquintana.com.ar/blogging/2009/05/23/aspnet-mvc-testing-a-custom-authorize-filters/

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, June 22, 2011 #

If you have large files in a content source that is being indexed by Sharepoint you might run into the following error message:

“The file reached the maximum download limit. Check that the full text of the document can be meaningfully crawled.”

This is usually caused because SharePoint’s MaxDownloadSize setting is set lower than the size of the file you are attempting to index. You can increase this value, restart the service then kick off a full crawl in order to fix this issue, but SharePoint 2007 and 2010 have different methods for accomplishing this task.

 

Sharepoint 2007

Open up the Registry editor and increase the MaxDownloadSize value to a number (in MB) higher than the largest file being indexed. You can find this at:

HKEY_LOCAL_MACHINE\Software\Microsoft\Search\1.0\Gathering Manager

After you increase the size, cycle the search service and kick off a full crawl of the content source in question.

 

Sharepoint 2010

With SharePoint 2010 you can use PowerShell via the Sharepoint 2010 Console in order to change the MaxDownloadSize. Execute the following commands to update the value:

   1: $ssa = Get-SPEnterpriseSearchServiceApplication
   2: $ssa.SetProperty(“MaxDownloadSize”, <new size in MB>)
   3: $ssa.Update()

 

References:

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

http://blogs.technet.com/b/brent/archive/2010/07/19/sharepoint-server-2010-maxdownloadsize-and-maxgrowfactor.aspx

 

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

A month or so ago I was working on a feature for a project that required a level of anonymity on the Sharepoint site in order to function. At the same time I was also working on another feature that required access to the Sharepoint search.asmx web service. I found out, the hard way, that the Sharepoint Web Services do not operate in an expected way while the IIS site is under anonymous access. Even though these web services expect requests with certain permissions (in theory) they never attempt to request those credentials when the web service is contacted. As a result the services return a 401 Unauthorized response.

The fix for my situation was to restrict anonymous access to the area that needed it (in this case the control in question had support for being used in an ASP.NET app that I could throw in a virtual directory). After that I removed anonymous access from IIS for the site itself and the QueryService requests were working once more.

Here’s a related article with a bit more depth about a similar experience:
http://chrisdomino.com/Blog/Post/401-Reasons-Why-SharePoint-Web-Services-Don-t-Work-Anonymously?Length=4

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Wednesday, May 11, 2011 #

If you’ve recently upgraded to SP1 and tried to build a solution checked out from TFS you might have come across the following dialog. Not only does it not allow you to cancel the build process, but it also REPEATEDLY THROWS THE DIALOG PREVENTING YOU FROM STOPPING THE PROCESS. Very annoying.

 

image

 

There is a hotfix available via connect and code gallery that will stop this problem.

Connect Bug Entry:
http://connect.microsoft.com/VisualStudio/feedback/details/650587/vs-2010-sp1-changes-packagecode-in-vdproj-on-each-build-but-fails-as-source-controlled

Hotfix download:
http://connect.microsoft.com/VisualStudio/Downloads/DownloadDetails.aspx?DownloadID=35848
http://archive.msdn.microsoft.com/KB2529927

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Thursday, March 10, 2011 #

When using XPath in .NET one of the gotchas to be aware of is that all namespaces must be named, otherwise you’ll end up with no results. Default namespaces that are specified with xmlns alone still need to be recognized in the XPath query!

Say I had a bit of XML like what is returned from the QueryService web service in Sharepoint:

   1: <?xml version="1.0" encoding="UTF-8"?>
   2: <ResponsePacket xmlns="urn:Microsoft.Search.Response">
   3:   <Response>
   4:     <Range>
   5:       ...
   6:       <Results>
   7:         <Document xmlns="urn:Microsoft.Search.Response.Document" relevance="849">
   8:             ...

 

When consuming and navigating this response with XPath it is necessary to name all namespaces. Then those named namespaces must be used in reference to the individual element being requested (i.e. doc:Document).

In VB:

   1: Dim xdoc = new XPathDocument(reader)
   2: Dim nav = xdoc.CreateNavigator()
   3: Dim nsMgr = new XmlNamespaceManager(nav.NameTable)
   4: nsMgr.AddNamespace("resp", "urn:Microsoft.Search.Response")
   5: nsMgr.AddNamespace("doc", "urn:Microsoft.Search.Response.Document")
   6:  
   7: Dim results = nav.Select("//doc:Document", nsMgr)

 

In C#:

   1: var xdoc = new XPathDocument(reader);
   2: var nav = xdoc.CreateNavigator();
   3: var nsMgr = new XmlNamespaceManager(nav.NameTable);
   4:  
   5: nsMgr.AddNamespace("resp", "urn:Microsoft.Search.Response");
   6: nsMgr.AddNamespace("doc", "urn:Microsoft.Search.Response.Document");
   7:  
   8: var results = nav.Select("//doc:Document", nsMgr);
  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati

Tuesday, February 08, 2011 #

I’ll be speaking tomorrow at the BRDNUG / BRSSUG joint meeting for their lightning round session. I’ll be giving a 15 minute introductory session on “Getting Started with F#” so please stop by and give me heckles.

For meeting details, check out the link below. Hope to see you there!

http://www.brdnug.org/events_view.aspx?eventid=50

  • Share This Post:
  • Share on Twitter
  • Share on Facebook
  • Share on Technorati