Archive

Archive for March, 2011

WCF 4.0 REST tip: File-less activation

March 15, 2011 2 comments

With WCF 3.5, it was always a problem that the service URL’s of REST applications were ending with “.svc”. This was not very RESTfull. One of the new features in WCF 4.0 is the ability to register services for use in IIS without having to rely on “.svc” files. The syntax to configure this is simple:

<configuration>
	<system.serviceModel>
		<serviceHostingEnvironment>
			<serviceActivations>
				<add relativeAddress="Hello" service="MyNameSpace.HelloService" factory="MyNameSpace.MyServiceHostFactory"/>
			</serviceActivations>
		</serviceHostingEnvironment>
	</system.serviceModel>
</configuration>

The following configuration would allow IIS to host the service using the URL:

http//localhost:<portnumber>/<websitename>/Hello

The factory attribute is optional; it allows you to specify a ServiceHostFactory for your service.

Advertisements
Categories: C#, WCF

Adding support for nested files in custom Visual Studio project types with MPF

March 10, 2011 1 comment

MPF, short for Managed Package Framework, is a great wrapper library to develop custom Visual Studio packages in C#, but it does not seem to cover everything that is possible within Visual Studio 2010. One of the things it does not provide out of the box is support for so called nested files in custom project types: having a “.xaml” file and below it having the corresponding “.xaml.cs” file. The official Visual Studio C# project type has support for this.

related files

Being a motivated programmer, this of course did not prevent me from implementing this functionality myself. In this article I will explain what you need to do in MPF to support this in your custom project types.

First, we need to override the method “AddNewFileNodeToHierarchy” of our ProjectNode implementation.

protected override void AddNewFileNodeToHierarchy(HierarchyNode parentNode, string path)
{
    if (IsRelatedFile(path) && (parentNode is FolderNode || parentNode is ProjectNode))
    {
        for (HierarchyNode child = parentNode.FirstChild; child != null; child = child.NextSibling)
        {
            string childPath = child.Url;
            if (IsParentOfRelatedFile(childPath, path))
            {
                base.AddNewFileNodeToHierarchy(child, path);
                child.Collapse(); // By default the node would be expanded, we don't want that...
                return; // Correct parent found
            }
        }
    }

    // Not a related file or the parent was not found, add using base functionality
    base.AddNewFileNodeToHierarchy(parentNode, path);
}

This new implementation uses a couple of helper functions.

“IsRelatedFile” should return true if the file is related:

private bool IsRelatedFile(string path)
{
    string extension = Path.GetExtension(path).ToLowerInvariant();

    switch (extension)
    {
        case ".diagram":
        case "your related file extensions ...":
            return true;
        default:
            return false;
    }
}

“IsParentOfRelatedFile” should return true if a node is the matching parent for a given related file:

private bool IsParentOfRelatedFile(string parentPath, string path)
{
    string extension = Path.GetExtension(path);

    return path.Equals(parentPath + extension, StringComparison.InvariantCultureIgnoreCase);
}

“Collapse” is an extension method I have created to collapse nodes in Visual Studio. We have to do this, because otherwise the parent of our related node will always be expanded when we add the nodes to the project. This is visually not appealing.

        public static void Collapse(this HierarchyNode node)
        {
            IVsUIHierarchyWindow uiWindow = UIHierarchyUtilities.GetUIHierarchyWindow(node.ProjectMgr.Site,
                HierarchyNode.SolutionExplorer);
            if (uiWindow != null)
            {
                ErrorHandler.ThrowOnFailure(uiWindow.ExpandItem(node.ProjectMgr, node.ID, EXPANDFLAGS.EXPF_CollapseFolder));
            }
        }

With this in place Visual Studio will already add a parent file and is related file correctly in in the Solution explorer of Visual Studio. But you will notice a very annoying behavior: Visual Studio gives our parent file the behavior of folder; double clicking on it will expand or collapse it. Yet in order to mimic the behavior of the standard C# project type, we only want that our parent file is opened in the editor of Visual Studio, not expanded or collapsed. So we have to intercept the double click and enter behavior of our parent node.

To do this, we have to override the method “ExecCommandOnNode” of our FileNode implementation:

protected override int ExecCommandOnNode(Guid cmdGroup, uint cmd, uint nCmdexecopt, IntPtr pvaIn, IntPtr pvaOut)
{
    if (cmdGroup == VsMenus.guidVsUIHierarchyWindowCmds)
    {
        switch (cmd)
        {
            case (uint)VSConstants.VsUIHierarchyWindowCmdIds.UIHWCMDID_DoubleClick:
            case (uint)VSConstants.VsUIHierarchyWindowCmdIds.UIHWCMDID_EnterKey:
                this.DoDefaultAction();
                return VSConstants.S_FALSE; // We do not want that the node is expanded in the solution view
        }

    }
    return base.ExecCommandOnNode(cmdGroup, cmd, nCmdexecopt, pvaIn, pvaOut);
}

Now our custom project supports nested files! Glimlach

Undocumented parameters of the WCF Service Moniker

March 6, 2011 1 comment

By looking at the .Net assemblies with Reflector, I have found parameters for the WCF service moniker that were not described in the documentation of Microsoft at the moment of writing this article. They can be found in the internal enum “System.ServiceModel.ComIntegration.MonikerHelper.MonikerAttribute”.

MonikerAttribute

I think that the meaning of each attribute should be pretty clear for people with WCF experience. All these attributes can be used as parameters for the WCF service moniker connection string.

  • Address: the address of the WCF service
  • Contract: the name of the contract of the WCF service
  • Wsdl: the complete WSDL of the WCF service
  • SpnIdentity: the expected Server Principal Name (SPN) identity of the WCF service endpoint.
  • UpnIdentity: the expected User Principal Name (UPN) identity of the WCF service endpoint. This is the logon name of the service on the network.
  • DnsIdentity: the dns (or the subject if the dns field is null) of an X.509 certificate used to authenticate the WCF service endpoint.
  • Binding: the binding of the WCF service
  • BindingConfiguration: the name of the binding configuration in the <appname.exe>.config file.
  • MexAddress: the MEX address of the WCF service
  • MexBinding: the MEX binding type of the WCF service
  • MexBindingConfiguration: the name of the mex binding configuration in the <appname.exe>.config file.
  • BindingNamespace: The binding name space of the WCF service.
  • ContractNamespace: The contract name space of the WCF service.
  • MexSpnIdentity: the expected Server Principal Name (SPN) identity of the MEX endpoint of the WCF service
  • MexUpnIdentity: the expected User Principal Name (UPN) identity of the MEX endpoint of the WCF service. This is the logon name of the service on the network.
  • MexDnsIdentity: the dns (or the subject if the dns field is null) of an X.509 certificate used to authenticate the MEX endpoint of the WCF service.
  • Serializer: the serializer to use (the DataContract serializer or the old XML serializer)
Categories: Advanced, C#, WCF