mikeobrien.net Curriculum Vitae Blog Labs
Tuesday, June 09, 2009

Why, why, why? Is it not possible that someone would want to parse a relative uri that has a querystring? M$, why do you impose these needless limits? Ok, so lets say we have the following UriTemplate:

/books/?language={language}

And you want to pick this uri apart and grab the querystring portion. You can load it into a Uri as relative but the Query and Segments properties will not be accessible and you will get the following exception: "This operation is not supported for a relative URI." There is a simple workaround but I really don't think we should have to do this. Basically you pass in a dummy base uri along with your relative one and this does the trick:

Uri myUri = new Uri(new Uri("dummy:"), "/books/?language={language}");
System.Diagnostics.Debug.Print(myUri.Query);

If you want to vote on changing this, click here for the Microsoft Connect feedback page.

Tuesday, June 09, 2009 4:55:31 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [1]  |  Trackback

If you attempt to define a GET operation that accepts an entity body with WCF REST like this:

[ServiceContract]
public interface IService
{
    [WebGet(UriTemplate = "/")]
    [OperationContract]
    ComplexFilter Search(ComplexFilter filter);
}

You will encounter the following error:

Operation 'xyz' in contract 'abc' uses GET, but also has body parameter 'lmnop'. GET operations cannot have a body. Either make the parameter 'lmnop' a UriTemplate parameter, or switch from WebGetAttribute to WebInvokeAttribute.

Who says that sending an entity body with a GET request is a bad thing?? RFC 2616 sure doesn't (See here and here). The spec neither explicitly allows (As it does for POST and PUT) or disallows sending an entity body. Interestingly M$ does allows sending an entity body with a DELETE operation even though the the spec for DELETE is just as silent about it as it is with GET, shouldn't it be the same restriction? All that is said in the spec is that GET should be used to retrieve an entity and it must be safe and idempotent. It seems clear that this doesn't rule out sending an entity body. If you have an opinion please leave a comment as I'm really interested in hearing what others have to say about this (Or here regarding this on Microsoft Connect). I could be totally wrong on this one but it looks like sending an entity body with a GET request is indeed RESTful.

UPDATE: Ok, this issue is a little more complex than I thought. Basically there isn't anything that says you cant do this (Like in RFC 2616) but the lack of specific direction in the spec makes it prohibitive. Leonard Richardson kindly gave me some feedback on this and pointed out a few issues:

"It's not illegal in the sense that the server must reject such a request, but it's also not defined. The definitions of PUT and POST say what to do with the entity-body, and the definitions of GET and DELETE don't. So you can do what you want, but you'll have trouble explaining what you mean and operating with other pieces of web machinery.

...because this behavior is undefined, the server can do anything it wants when it gets such a request--including rejecting the request...

The main reason to use GET instead of POST here is that you want the data to be cacheable on the client side or by an intermediary. But if you put selection information in the entity-body of a GET request, I don't think there's a cache in the world that will cache that response correctly."

So if you want to do this you'll need to beware of these issues. It seems like its really not a good idea if the resources are Internet facing (Which is probably the vast majority of RESTful services). You may be able to get away with it in an intranet since the environment will be predictable. All in all its probably a better idea to just use POST and rework your resources (Which Leonard also suggested). WCF was indeed being safe in its implementation so I guess I have to eat my words... :)

Now if you think it's bogus that M$ disallows this don't despair! You can trick the WCF REST API into allowing this. It takes a bit of jumping through hoops though. First you need to create a custom WebServiceHost and factory as follows:

public class WebServiceHostFactory : ServiceHostFactory
{
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {
        return new WebServiceHost(serviceType, baseAddresses);
    }
}
public class WebServiceHost : System.ServiceModel.Web.WebServiceHost
{
    public WebServiceHost(
        Type serviceType, params Uri[] baseAddresses)
        : base(serviceType, baseAddresses) { }

    public WebServiceHost(
        object singletonInstance, params Uri[] baseAddresses)
        : base(singletonInstance, baseAddresses) { }

    protected override void OnOpening()
    {
        base.OnOpening();
        ReplaceBehaviorOnAllEndpoints(this,
            typeof(System.ServiceModel.Description.WebHttpBehavior),
            new WebHttpBehavior());

    }

    public void ReplaceBehaviorOnAllEndpoints(
        ServiceHostBase serviceHost, 
        Type replaceType,
        IEndpointBehavior behavior)
    {
        foreach (var endpoint in serviceHost.Description.Endpoints)
        {
            if (replaceType != null)
            {
                IEndpointBehavior exisitingBehavior = endpoint.Behaviors.FirstOrDefault(
                    b => b.GetType() == replaceType);
                if (exisitingBehavior != null)
                    endpoint.Behaviors.Remove(exisitingBehavior);
            }
            endpoint.Behaviors.Add(behavior);
        }
    }
}

Now create the custom WebHttpBehavior. We're basically creating a surrogate behavior with all the same properties except we set the method to a bogus value. We apply this behavior before the code executes that imposes the restriction (In GetRequestDispatchFormatter). Then afterwards we remove the surrogate and reapply the original behavior.

public class WebHttpBehavior : System.ServiceModel.Description.WebHttpBehavior
{
    #region WebHttpBehavior Overrides
        protected override IDispatchMessageFormatter GetRequestDispatchFormatter(
              OperationDescription operationDescription, ServiceEndpoint endpoint)
        {
            IOperationBehavior originalBehavior = null; 
            IOperationBehavior surrogateBehavior = null;

            TryGetSurrogateBehavior(operationDescription,
                                    ref originalBehavior,
                                    ref surrogateBehavior);

            SwapBehaviors(operationDescription, originalBehavior, surrogateBehavior);

            IDispatchMessageFormatter formatter = base.GetRequestDispatchFormatter(operationDescription, endpoint);

            SwapBehaviors(operationDescription, surrogateBehavior, originalBehavior);

            return formatter;
        }

    #endregion

    #region Private Methods

        private void SwapBehaviors(OperationDescription operationDescription, 
                                   IOperationBehavior remove, IOperationBehavior add)
        {
            if (remove != null && add != null)
            {
                operationDescription.Behaviors.Remove(remove);
                operationDescription.Behaviors.Add(add);
            }
        }

        private void TryGetSurrogateBehavior(OperationDescription operationDescription, 
                         ref IOperationBehavior original, ref IOperationBehavior surrogate)
        {
            if (!IsUntypedMessage(operationDescription.Messages[0]) && 
                operationDescription.Messages[0].Body.Parts.Count != 0)
            {
                WebGetAttribute webGetAttribute = 
                          operationDescription.Behaviors.Find<WebGetAttribute>();
                if (webGetAttribute != null)
                {
                    original = webGetAttribute;
                    surrogate = new WebInvokeAttribute() {
                         BodyStyle = webGetAttribute.BodyStyle,
                         Method = "NONE",
                         RequestFormat = webGetAttribute.RequestFormat,
                         ResponseFormat = webGetAttribute.ResponseFormat,
                         UriTemplate = webGetAttribute.UriTemplate };
                }
                else
                {
                    WebInvokeAttribute webInvokeAttribute = 
                        operationDescription.Behaviors.Find<WebInvokeAttribute>();
                    if (webInvokeAttribute != null && webInvokeAttribute.Method == "GET")
                    {
                        original = webInvokeAttribute;
                        surrogate = new WebInvokeAttribute() {
                            BodyStyle = webInvokeAttribute.BodyStyle,
                            Method = "NONE",
                            RequestFormat = webInvokeAttribute.RequestFormat,
                            ResponseFormat = webInvokeAttribute.ResponseFormat,
                            UriTemplate = webInvokeAttribute.UriTemplate };
                    }
                }
            }
        }

        private bool IsUntypedMessage(MessageDescription message)
        {
            if (message == null)
            {
                return false;
            }
            return ((((message.Body.ReturnValue != null) && 
                (message.Body.Parts.Count == 0)) && 
                (message.Body.ReturnValue.Type == typeof(Message))) || 
                (((message.Body.ReturnValue == null) && (message.Body.Parts.Count == 1)) && 
                (message.Body.Parts[0].Type == typeof(Message))));
        }

    #endregion
}
.NET 3.5 | REST | WCF
Tuesday, June 09, 2009 5:09:13 AM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Monday, June 08, 2009

Evidentially the request message isn't guaranteed to be around by the time you get to your response code. I found out this the hard way when I was getting sporadic failures accessing properties of the IncomingWebRequestContext in response code. To get around this I just stashed info (While in request code) I was interested in, in the outgoing message properties. Then I retrieve these properties in my response code.

Using the outgoing message properties approach is pretty easy. To give you a little background, I have an error handler behavior that attaches a specified error handler to all channel dispatchers in a particular service. I also have a custom error handler that logs exceptions to a specified object that implemented a particular logging interface. This error handler passes the request http info to the logger. Originally I was directly accessing the IncomingWebRequestContext in the HandleError method of the error handler to get this request info and would sporadically get the error in the title. Now in my error handler behavior I'm adding a message inspector that will add the request http info to the outgoing message properties (I'm piggy backing off the error handler behavior to do this because they are so closely related):

public class ErrorHandlerBehavior : IServiceBehavior
{
    public const string HttpRequestInformationProperty = "HttpRequestInformation";

    public void ApplyDispatchBehavior(
            ServiceDescription serviceDescription, 
            ServiceHostBase serviceHostBase)
    {
       foreach (ChannelDispatcher dispatcher in 
                serviceHostBase.ChannelDispatchers)
       {
            // Add the error handler...

            // Add the parameter inspector that gets the request info and
            // stores it in the outgoing message properties
            foreach (EndpointDispatcher endpoint in dispatcher.Endpoints)
                  endpoint.DispatchRuntime.MessageInspectors.Add(
                       new HttpRequestInformationInspector());
       }
    }
}

So now error handlers have this info at their disposal. Then in the message inspector we grab the http request info and stash it in the outgoing message properties:

private class HttpRequestInformationInspector : IDispatchMessageInspector   
{
    public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
    {
        HttpRequestInformation info = new HttpRequestInformation();

        string contentLengthHeader =
            WebOperationContext.Current.IncomingRequest.Headers[HttpRequestHeader.ContentLength];

        long contentLength;
        if (!string.IsNullOrEmpty(contentLengthHeader))
            long.TryParse(contentLengthHeader, out contentLength);
        else
            contentLength = -1;

        info.ContentLength = contentLength;
        info.Uri = OperationContext.Current.IncomingMessageHeaders.To;
        info.Method = WebOperationContext.Current.IncomingRequest.Method;
        info.ContentType = WebOperationContext.Current.IncomingRequest.ContentType;
        info.Accept = WebOperationContext.Current.IncomingRequest.Accept;
        info.UserAgent = WebOperationContext.Current.IncomingRequest.UserAgent;
        info.Headers = WebOperationContext.Current.IncomingRequest.Headers;

        OperationContext.Current.OutgoingMessageProperties.Add(
            HttpRequestInformationProperty, info);
        return null;
    }

    public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState) { }
}
public class HttpRequestInformation
{
    public Uri Uri { get; set; }
    public string Method { get; set; }
    public string ContentType { get; set; }
    public long ContentLength { get; set; }
    public string Accept { get; set; }
    public string UserAgent { get; set; }
    public WebHeaderCollection Headers { get; set; }
}

Note that I'm manually grabbing the content length from the headers. Interestingly the content length header may not always be present. And its absence may not mean that the content length is zero (That's why I return a negative number if it is absent). The problem is the IncomingWebRequestContext ContentLength property does not check for the existence of the header before it parses it. So if its not there (Which is what's going to happen with a GET request) it will throw a null ref exception (Which can be confusing). I have submitted feedback here it you want to read more about this and Microsoft's response.

So now it's available in response code:

public bool HandleError(Exception error)
{
    HttpRequestInformation info;

    if (OperationContext.Current.OutgoingMessageProperties.ContainsKey(
        ErrorHandlerBehavior.HttpRequestInformationProperty))
        info = (RequestInformation)OperationContext.Current.OutgoingMessageProperties[
            ErrorHandlerBehavior.HttpRequestInformationProperty];
    else
        info = new RequestInformation();

    LogHandler.Write(error, info);
    return true;
}

Do you know of a better way to handle this? If so, please leave a comment as I'm not 100% satisfied with this approach and would be interested in a simpler alternative.

Monday, June 08, 2009 6:51:57 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback

I'm now to the point where I have more than one source file in an F# project (Woo hoo!) and the issue of entry point came up. Here is what the language spec says about it (As of 1.9.6):

"12.1.4 Explicit “Main” Entry Point

The last file specified in the compilation order for a .EXE may additionally contain an explicit entry point, indicated by annotating a function in a module with EntryPointAttribute.

     - The attribute can be applied only to a let-bound function in a module. It may not be a member.

     - Only one function may be given this attribute, and this must be the last declaration in the last file processed on the command line. The function may be in a nested module.

     - The function is asserted to have type “string[] -> int” prior to being checked. If this assertion fails an error is reported.

     - At runtime the arguments passed on startup are an array containing the same as entries as System.Environment.GetCommandLineArgs(), minus the first entry in that array.

The function becomes the entry point to the program. It immediately forces the static initializer for the file in which the function exists. It will then run the body of the function."

.NET 3.5 | F#
Monday, June 08, 2009 2:12:30 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [1]  |  Trackback
Tuesday, May 26, 2009

One of the things I really wanted with our REST API is per method basic authentication. So lets say we have a library with a books resource. We want everyone to be able to read this resource but we want people to authenticate when modifying this resource. As far as I could tell there is no way to do this OOB with WCF REST without resorting to breaking your resource up into two parts, read and write and hosting the secure one in a separate IIS app with basic auth enabled. The only way I could figure out how to do this properly is implement basic auth in an operation invoker. This way you could define authentication on a per method basis as follows (With the BasicAuthenticationInvoker) without breaking the resource up:

[ServiceContract]
public interface IBookService
{
    [WebGet(UriTemplate = "/{isbn}")]
    [OperationContract]
    Book GetBook(string isbn);
            
    [WebInvoke(UriTemplate = "/{isbn}", Method=Verbs.Delete)]
    [OperationContract]
    [BasicAuthenticationInvoker]
    void DeleteBook(string isbn);
}

It's pretty simple to do this and doesn't require integration with IIS. First define a class that will act as a behavior attribute and an operation invoker:

public class BasicAuthenticationInvoker : Attribute, IOperationBehavior, IOperationInvoker 
{
}

Next, implement the operation behavior. We will store the original invoker to call if the user successfully authenticates, our invoker will basically act as a proxy. We can ignore the other three implemented methods.

#region Private Fields

    private IOperationInvoker _invoker;

#endregion

#region IOperationBehavior Members

    public void ApplyDispatchBehavior(OperationDescription operationDescription, 
        DispatchOperation dispatchOperation)
    {
        _invoker = dispatchOperation.Invoker;
        dispatchOperation.Invoker = this;
    }

    public void ApplyClientBehavior(OperationDescription operationDescription, 
        ClientOperation clientOperation) { }
    public void AddBindingParameters(OperationDescription operationDescription, 
        BindingParameterCollection bindingParameters) { }
    public void Validate(OperationDescription operationDescription) { }

#endregion

Now implement the operation invoker. First we call our private authenticate method, if this is successful we'll call the invoker, otherwise we return nothing.

#region IOperationInvoker Members

    public object Invoke(object instance, object[] inputs, out object[] outputs)
    {
        if (Authenticate("New York Public Library"))
            return _invoker.Invoke(instance, inputs, out outputs);
        else
        {
            outputs = null;
            return null;
        }
    }

    public object[] AllocateInputs() { return _invoker.AllocateInputs(); } 

    public IAsyncResult InvokeBegin(object instance, object[] inputs, 
        AsyncCallback callback, object state)
    { throw new NotSupportedException(); }

    public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
    { throw new NotSupportedException(); }

    public bool IsSynchronous { get { return true; } }

#endregion

The private authentication methods are as follows. The authenticate method checks the username and password and if successful returns true, otherwise it sets the authenticate header and the status code to unauthorized.

private bool Authenticate(string realm)
{
    string[] credentials = 
        GetCredentials(WebOperationContext.Current.IncomingRequest.Headers);

    if (credentials != null && 
        credentials[0] == "tony" && 
        credentials[1] == "clifton") return true;

    WebOperationContext.Current.OutgoingResponse.Headers["WWW-Authenticate"] = 
        string.Format("Basic realm=\"{0}\"", realm);
    WebOperationContext.Current.OutgoingResponse.StatusCode = 
        HttpStatusCode.Unauthorized;
    return false;
}

private string[] GetCredentials(WebHeaderCollection headers)
{
    string credentials = WebOperationContext.Current.IncomingRequest.
        Headers["Authorization"];
    if (credentials != null) credentials = credentials.Trim();

    if (!string.IsNullOrEmpty(credentials))
    {
        try
        {
            string[] credentialParts = credentials.Split(new char[] { ' ' });
            if (credentialParts.Length == 2 && 
                credentialParts[0].Equals("basic", 
                StringComparison.OrdinalIgnoreCase))
            {
                credentials = ASCIIEncoding.ASCII.GetString(
                    Convert.FromBase64String(credentialParts[1]));
                credentialParts = credentials.Split(new char[] { ':' });
                if (credentialParts.Length == 2) return credentialParts;
            }
        }
        catch { }
    }

    return null;
}

This same approach could also be used to examine parameters as part of the authentication process (If you are using tokens or the like).

.NET 3.5 | REST | WCF
Tuesday, May 26, 2009 7:47:08 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [2]  |  Trackback
Thursday, May 21, 2009

This is really lame. I'm creating a custom service host (That inherits from WebServiceHost) and I want to be able to programmatically add behaviors from configuration. Since the WebServiceHost is zero config there are no service elements to define a behavior config. Now I know I could manually create those service elements with an webHttpBinding and specify the behavior config, but I really do like the zero configuration feature, I just want to be able to define behaviors in config. Unfortunately the BehaviorExtensionElement's CreateBehavior is marked as internal. I'm not sure if M$ will make this public in the future or not but it looks like the only good way to get around it for now is with reflection (Or create a dummy service element with the behavior config, have the runtime load the behaviors and then copy them to your service, boo). I think in this instance reflection on an internal member is safe as that method has to be there in order for the behavior to be created by the runtime. I don't see how it can be changed since that would break custom behaviors. I snagged this simple extension method from the aforementioned thread, it uses reflection to invoke the internal CreateBehavior method.

public static object CreateBehavior(this BehaviorExtensionElement extensionElement)
{
    return extensionElement.GetType().
        GetMethod(
            "CreateBehavior",
            System.Reflection.BindingFlags.Instance |
            System.Reflection.BindingFlags.NonPublic).
                Invoke(extensionElement, new object[0] { });
}

I also whipped up a few ServiceHost extension methods that add the behaviors (Adapted from some reflected framework code):

public static void LoadBehaviors(
    this ServiceHost serviceHost,
    string behaviorConfiguration)
{
    ServiceBehaviorElement serviceBehaviors = 
        GetServiceBehaviorElement(serviceHost, behaviorConfiguration);
    if (serviceBehaviors != null)
    {
        foreach (BehaviorExtensionElement behaviorExtension in serviceBehaviors)
        {
            object extension = behaviorExtension.CreateBehavior();
            if (extension != null)
            {
                Type extensionType = extension.GetType();
                if (typeof(IServiceBehavior).IsAssignableFrom(extensionType))
                {
                    if (serviceHost.Description.Behaviors.Contains(extensionType))
                    {
                        serviceHost.Description.Behaviors.Remove(extensionType);
                    }
                    serviceHost.Description.Behaviors.Add((IServiceBehavior)extension);
                }
            }
        }
    }
}

public static ServiceBehaviorElement GetServiceBehaviorElement(
    this ServiceHost serviceHost, string behaviorConfiguration)
{
    BehaviorsSection behaviorsSection = 
        (BehaviorsSection)ConfigurationManager.
        GetSection("system.serviceModel/behaviors");
    foreach (ServiceBehaviorElement behavior in behaviorsSection.ServiceBehaviors)
    {
        if (behavior.Name == behaviorConfiguration)
            return behavior;
    }
    return null;
}

Then you simply run this on the ServiceHost:

serviceHost.LoadBehaviors("myBehaviorConfig");

Now if your creating your own service host you can override the ApplyConfiguration method and add them there. In the following example I add a check to see if there is a service element for this service. If not then I apply the behaviors, otherwise I skip it and assume that the service element has the desired configuration.

protected override void ApplyConfiguration()
{
    base.ApplyConfiguration();
    if (!this.HasServiceElement())
        this.LoadBehaviors("myBehaviorConfig");
}
The following is the HasServiceElement & supporting GetServiceElement ServiceHost extension methods:
public static bool HasServiceElement(this ServiceHost serviceHost)
{
    return (GetServiceElement(serviceHost) != null);
}

public static ServiceElement GetServiceElement(this ServiceHost serviceHost)
{
    ServicesSection servicesSection = (ServicesSection)ConfigurationManager.
        GetSection("system.serviceModel/services");
    ServiceElementCollection services = servicesSection.Services;
    foreach (ServiceElement element in services)
    {
        if (element.Name == serviceHost.Description.ConfigurationName)
            return element;
    }
    return null;
}
.NET 3.5 | REST | WCF
Thursday, May 21, 2009 9:57:40 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Friday, May 15, 2009

I just submitted a few suggestions regarding the WCF/REST implementation. If you feel the same, please vote on them. If you don't agree with them, please leave a comment, I'd love to hear some thoughts on these issues.

REST/WCF Automatic Selection of Formatter Based On Accept & Content Type Headers

REST/WCF UriTemplate Querystring Parameter Name Case Sensitivity

REST/WCF UriTemplate Optional Querystring Parameters

.NET 3.5 | REST | WCF
Friday, May 15, 2009 6:06:19 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Wednesday, April 22, 2009

So here is the scenario on the service side: WCF, basicHttpBinding, UsernameToken Profile (No signing or encryption). On the client side we are working in Eclipse Ganymede, JRE 6, JDK 1.6 Update 13. The following steps outline how to consume the WCF service.

1) Download wss4j-1.5.7.jar from here (Pick a mirror) and save it to your Eclipse plugins folder (Or where ever you like). More information about wss4j can be found here.

2) Download xml-security-bin-1_4_2.zip from here and unzip it into temporary folder. Copy the contents of the libs folder into a subfolder under the Eclipse plugins folder called org.apache.xml.security_1.4 (Or where ever you like). More information about Apache XML Security can be found here.

3) If you haven't already done so create a new Java project and add references to the wss4j-1.5.7.jar and org.apache.xml.security_1.4\xmlsec-1.4.2.jar file.

4) If you haven't already, install the Web Services Tools (WST). Go to "Help|Software Updates" and select the "Available Software" tab. Expand the "Web Tools (WTP) Update Site" node and check the "Web Tools Platform (WTP) x.x.x" node. Then click the "Install" button. Opt to restart the IDE after the install.

image

5) Next right click your project and select "New|Other". Scroll down and expand the "Web Services" node and select "Web Service Client" and click Next:

image

6) Enter the url to the WSDL and make sure the "Client type" is set to "Java Proxy". Next under "Configuration" the "Web service runtime" should be "Apache Axis" and the "Client project" should be your project, if not click the property link and make the appropriate modifications. Move the slider all the way down until it is set to "Develop client".

image

7) Create a new class called Credentials and paste in the following code:

import javax.security.auth.callback.Callback;
import org.apache.axis.client.Stub;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.handler.WSHandlerConstants;
import javax.security.auth.callback.CallbackHandler;

public class Credentials
{
    static class PasswordCallback implements CallbackHandler {
        private String password;
        public PasswordCallback(String password)
        { this.password = password; }
        public void handle(Callback[] callbacks) 
        {((WSPasswordCallback)callbacks[0]).setPassword(this.password); }
    }
    
    public static void Add(Stub stub, String username, String password)
    {
        stub._setProperty(WSHandlerConstants.USER, username);
        stub._setProperty(WSHandlerConstants.PW_CALLBACK_REF, 
                            new PasswordCallback(password));
    }
}

8) Create a new file called ServiceConfig.wsdd and paste in the following xml:

<deployment xmlns="http://xml.apache.org/axis/wsdd/" 
            xmlns:java="http://xml.apache.org/axis/wsdd/providers/java">
  <transport name="http" 
             pivot="java:org.apache.axis.transport.http.HTTPSender"/>
  <globalConfiguration >
    <requestFlow >
      <handler type="java:org.apache.ws.axis.security.WSDoAllSender" >
        <parameter name="action" value="UsernameToken"/>
        <parameter name="passwordType" value="PasswordText"/>
      </handler>
    </requestFlow>
    <responseFlow>
      <handler type="java:org.apache.ws.axis.security.WSDoAllReceiver">
        <parameter name="action" value="Timestamp"/>
      </handler>
    </responseFlow>
  </globalConfiguration >
</deployment>

9) If one is not already created then create a class called Startup and paste in the following code. Note, you must specify the bracketed portions as they will be named differently depending on the service and its WSDL.

import <ServiceNamespace>.*;
import org.apache.axis.*;
import java.rmi.RemoteException;
import org.apache.axis.client.Stub;
import javax.xml.rpc.ServiceException;
import org.apache.ws.security.handler.*;
import org.apache.axis.configuration.FileProvider;

public class Startup 
{
    public static void main(String[] args) throws RemoteException, ServiceException 
    {
        EngineConfiguration config = new FileProvider("ServiceConfig.wsdd");
        <ServiceName>ServiceLocator locator = new <ServiceName>ServiceLocator(config);
        <ServiceInterface> service = locator.get<ServiceStub>();
        
        Credentials.Add((Stub)service, "Username", "P@$$w0rd");

        <ResultType> result = service.<Method>();
        System.out.println(result);
    }
}

 

At this point you should be able to successfully consume the target service.

Wednesday, April 22, 2009 11:22:28 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Friday, April 17, 2009

I have been struggling all week trying to get a client created with the NetBeans 6.5.1 IDE to communicate with a WCF service using the wsHttpBinding. The symptoms were that it would connect and just hang when I made the soap call. I took a look at the message that was being sent across the wire and I noticed that JAX-WS was not sending the WS-Addressing headers. So after much searching and hitting the Metro message board and gave up and moved onto something else. While I was working on that something else I happened to look at the "port" factory method on the proxy that's generated by wsimport and noticed that you could pass multiple "WebServiceFeature"s, one of which was one for WS-Addressing! Passed that in and voila, it worked! Here is an example:

try { // Call Web Service Operation
    yada.SystemService service = new yada.SystemService();
    yada.Sys port = service.getYadaSystem(new AddressingFeature(true, true));
    // TODO process result here
    yada.VersionInfo result = port.getVersion();
    System.out.println("Result = "+result);
} catch (Exception ex) {
    System.out.println(ex.getMessage());
}

You can read more about this class here. I have no idea why wsimport doesent just bake this into the proxy as the policy in the WSDL clearly states that it uses WS-Addressing by way of the UsingAddressing element. Strange...

Friday, April 17, 2009 10:45:16 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Thursday, April 02, 2009

Today I wanted to setup a debugging page to read the trace log for our prototype WCF services and display the last 10 messages that have come across the wire. I'm using the XmlWriterTraceListener to write the entries. The XmlWriterTraceListener writes Xml fragments to the log file.  This is good and all but the problem is reading in the log. Since a well formed xml file can only have one root element the log cant be successfully parsed (As far as I could tell anyway's, if anyone knows of another way please let me know). So the only decent solution I could come up with was to create a reader that injects a root element.  The usage is simple, just pass in a stream or stream reader and the name of the root element:

XDocument log = XDocument.Load(
    new XmlFragmentTextReader(
        new FileStream(
            @"D:\Logs\Wcf.log", 
            FileMode.Open, 
            FileAccess.Read, 
            FileShare.ReadWrite), 
         "root"));

var entries = from entry in log.Element("root")
                  .Elements(
                    XName.Get(
                    "E2ETraceEvent", 
                    "http://schemas.microsoft.com/2004/06/E2ETraceEvent"))
              select entry;

foreach (XElement entry in entries)
{
    // Do Something...
}

Here is the implementation. Since the read/peek methods in the readers in the BCL are not virtual I'm forced to choose aggregation over inheritance. Only the Read and Peek methods need to be implemented as all other methods call these in the base TextReader class.

public class XmlFragmentTextReader : TextReader
{
    #region Private Members

        private enum Location
        { RootOpen, Fragments, RootClose }

        private StreamReader _fragmentReader;
        private Location _location = Location.RootOpen;
        private int _index = 0;
        private char[] _rootOpenBuffer;
        private char[] _rootCloseBuffer;

    #endregion

    #region Constructors

        public XmlFragmentTextReader(StreamReader reader, 
            string rootElementName) : base()
        {
            _fragmentReader = reader;
            _rootOpenBuffer = string.Format("<{0}>\r\n", 
                rootElementName).ToCharArray();
            _rootCloseBuffer = string.Format("\r\n</{0}>", 
                rootElementName).ToCharArray();
        }

        public XmlFragmentTextReader(Stream stream, 
            string rootElementName) : 
            this(new StreamReader(stream), rootElementName) { }

    #endregion

    #region Overridden Methods

        public override int Peek()
        {
            switch (_location)
            {
                case Location.RootOpen:
                    return _rootOpenBuffer[_index];
                case Location.Fragments:
                    return _fragmentReader.Peek();
                case Location.RootClose:
                    return _rootCloseBuffer[_index];
                default : return - 1;
            }
        }

        public override int Read()
        {
            switch (_location)
            {
                case Location.RootOpen:
                    if (_index < _rootOpenBuffer.Length)
                        return _rootOpenBuffer[_index++];
                    else
                    {
                        _location = Location.Fragments;
                        return Read();
                    }
                case Location.Fragments:
                    if (!_fragmentReader.EndOfStream)
                        return _fragmentReader.Read();
                    else
                    {
                        _location = Location.RootClose;
                        _index = 0;
                        return Read();
                    }
                case Location.RootClose:
                    if (_index < _rootCloseBuffer.Length)
                        return _rootCloseBuffer[_index++];
                    else return -1;
                default: return -1;
            }
        }

        public override void Close()
        { _fragmentReader.Close(); }

    #endregion
}

Like I said, if anyone knows of a better way please drop me a line!

.NET 3.5 | C# | Logging | XML/XSL
Thursday, April 02, 2009 11:47:17 PM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Wednesday, March 25, 2009

Looks like this has been done already in various ways on the web, I'll add mine to the mix. I just wanted a behavior that would allow me to select the error handler for a particular service and would be configurable. So I start off by creating a behavior extension element:

public class ErrorHandlerBehaviorElement : BehaviorExtensionElement
{
    #region BehaviorExtensionElement Overrides

        public override Type BehaviorType
        {
            get { return typeof(ErrorHandlerBehavior); }
        }

        protected override object CreateBehavior()
        {
            return new ErrorHandlerBehavior(Type.GetType(ErrorHandlerType));
        }

        [ConfigurationProperty("errorHandlerType", IsRequired = true)]
        public string ErrorHandlerType
        {
            get
            { return (string)base["errorHandlerType"]; }
            set
            { base["errorHandlerType"] = value; }
        }

    #endregion
}

This is really just a ConfigurationElement so you would add additional configuration as you normally would. I'm using the declarative approach above. Next, define the behavior:

public class ErrorHandlerBehavior : IServiceBehavior
{
    #region Private Fields

        private Type _type;

    #endregion

    #region Constructor

        public ErrorHandlerBehavior(Type type)
        {
            _type = type;
        }

    #endregion

    #region IServiceBehavior Members

        public void ApplyDispatchBehavior(
            ServiceDescription serviceDescription, 
            System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            IErrorHandler errorHandler = 
                (IErrorHandler)Activator.CreateInstance(_type);

            foreach (ChannelDispatcher dispatcher in 
                serviceHostBase.ChannelDispatchers)
            {
                dispatcher.ErrorHandlers.Add(errorHandler);
            }
        }

        public void AddBindingParameters(
            ServiceDescription serviceDescription, 
            System.ServiceModel.ServiceHostBase serviceHostBase, 
            System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, 
            System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        { }

        public void Validate(
            ServiceDescription serviceDescription, 
            System.ServiceModel.ServiceHostBase serviceHostBase)
        { }

    #endregion
}

In the ApplyDispatchBehavior method I create the error handler and add it to all the channel dispatchers in the service. The error handler itself is very simple; simply hides/logs any exceptions that are not FaultExceptions.

public class UnhandledFaultException : FaultException
{
    public UnhandledFaultException() :
        base("An unexpected error has occured. Please contact technical support for assistance.") { }
}
public class ErrorHandler : IErrorHandler 
{
    #region IErrorHandler Members

        public void ProvideFault(
            Exception error, 
            MessageVersion version, 
            ref Message fault)
        {
            if (!(error is FaultException))
            {
                FaultException exception = new UnhandledFaultException();
                MessageFault messageFault = exception.CreateMessageFault();
                fault = Message.CreateMessage(version, messageFault, exception.Action);
            }
        }

        public bool HandleError(Exception error)
        {
            if (!(error is FaultException))
            {
                // TODO: Log errors here
            }
            return false;
        }

    #endregion
}

Next, I need to add the behavior to my configuration. The Wcf Configuration Editor actually handled this very nicely. I was able to do it all visually. Here is the actual configuration:

<system.serviceModel>
    <extensions>
        <behaviorExtensions>
             <add name="errorHandler" 
                  type="MyLib.ErrorHandlerBehaviorElement, MyLib" />
        </behaviorExtensions>
    </extensions>
    <services>
        <service behaviorConfiguration="MyServiceBehavior" name="MyService">...</service>
    </services>
    <behaviors>
        <serviceBehaviors>
             <behavior name="MyServiceBehavior">
                 ...
                 <errorHandler errorHandlerType="MyLib.ErrorHandler, MyLib" />
             </behavior>
        </serviceBehaviors>
    </behaviors>
</system.serviceModel>

Further reading:

1) Programming WCF Services - Juval Lowy, Page 221 in 1st Edition

2) WCF, IErrorHandler and propagating faults

3) Implementing IErrorHandler

Wednesday, March 25, 2009 10:37:52 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [2]  |  Trackback
Thursday, March 19, 2009
Wednesday, January 21, 2009

I have been reading The .NET Developer's Guide to Windows Security and it mentioned that as of .NET 1.1 a calling threads principal is not automatically propagated to a thread spun off by the ThreadPool using the QueueUserWorkItem method; it has to be manually set. Looks like this has changed as of .NET 2.0 as the following test shows. It automatically propagates when the ThreadPool initiates a call with a thread in the pool, when using the APM and manually creating threads:

 

// Set the executing threads principle\identity
Thread.CurrentPrincipal = new GenericPrincipal(
    new GenericIdentity("Louis De Broglie"), null);

Action<string> writeInfo = new Action<string>((n) =>
    Console.WriteLine(string.Format("{0} - {1}", n,
    Thread.CurrentPrincipal.Identity.Name)));

// Test the executing thread
writeInfo.Invoke("Main Thread");

// Test queueing a worker item on the thread pool
ThreadPool.QueueUserWorkItem(x => 
    writeInfo.Invoke("Thread Pool Initiated Thread"));

// Test making an async call
Action asyncCall = new Action(() => 
    writeInfo.Invoke("Async Initiated Thread"));

asyncCall.BeginInvoke(ar => asyncCall.EndInvoke(ar), null);

// Test manually creating a thread
new Thread(() => 
    {
        writeInfo.Invoke("Manually Created Thread");

        // Set a new principal
        Thread.CurrentPrincipal = new GenericPrincipal(
            new GenericIdentity("Erwin Schrödinger"), null);

        writeInfo.Invoke("Manually Created Thread, new identity");

        // Test queueing a worker item on the thread pool
        ThreadPool.QueueUserWorkItem(x =>
            writeInfo.Invoke("Thread Pool Initiated Thread from a new Thread"));

        // Test making an async call
        asyncCall = new Action(() =>
            writeInfo.Invoke("Async Initiated Thread from a new Thread"));

        asyncCall.BeginInvoke(ar => asyncCall.EndInvoke(ar), null);

        // Test manually creating a thread from a thread
        new Thread(() => 
            writeInfo.Invoke("Manually Created Thread from a new Thread")
            ).Start();
    }).Start();

Console.ReadKey();
 

image

Wednesday, January 21, 2009 12:08:51 AM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Monday, January 19, 2009

The WindowsIdentity class offers a constructor that accepts a user principal name (username@domain.int) and doesn't require the password. This sounds like a great way to get a token for impersonation but there are some limitations. First of all the account must be an AD account and...

  1. To use it on the network you must use constrained delegation to grant permission to the source server to generate tokens (And mark restricted accounts as not authorized for delegation) and also which target servers can be accessed with the token generated.
  2. To use it locally to access secured resources (Like files, etc) the process needs to have the trusted computing base priviledge which is root access to the box.

Keith Brown covers this here in detail. Unfortunately if you need to impersonate a LSA account or you cant/dont want to use constrained delegation you have to use the LogonUser API call to get a token to pass to the WindowsIdentity constructor. This call requires the domain, username and password. The WindowsIdentity class doesent offer a constructor that does this so you have to roll your own. Below is a simple class I whipped up that will do this.

Interesting aside, the SafeUserTokenHandle class is actually defined in the FCL but marked internal. There are actually a number of SafeHandle derived classes in System.dll (Under the Microsoft.Win32.SafeHandles namespace). So if you need a SafeHandle for a handle for a particular API call you may be able to snag one here for "free" with Reflector.

Some further reading on this subject; MSDN - How To: Use Impersonation and Delegation in ASP.NET 2.0, The .NET Developer's Guide to Windows Security (Or free online here!) and Professional ASP.NET 3.5 Security, Membership, and Role Management with C# and VB.

Here is the usage:

using (WindowsImpersonationContext context = 
        Impersonation.Impersonate("domain", "username", P@$$w0rd, LogonSessionType.Network))
{
    //Do something...
}

Here is the class:

using System;
using System.ComponentModel;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Permissions;
using System.Security.Principal;
using System.Threading;
using Microsoft.Win32.SafeHandles;

public static class Impersonation
{
    #region Public Methods

        public static WindowsImpersonationContext Impersonate(
            string domain, string username, string password, LogonSessionType sessionType)
        {
            WindowsImpersonationContext impersonationContext = null;
            SafeUserTokenHandle token;

            if (LogonUser(
               username,
               domain,
               password,
               sessionType,
               LogonProvider.Default,
               out token))
            {
                using (token)
                {
                    impersonationContext = WindowsIdentity.Impersonate(
                        token.DangerousGetHandle());
                }
            }
            else
                throw new Win32Exception(Marshal.GetLastWin32Error());

            return impersonationContext;
        }

    #endregion

    #region Native Methods

        [DllImport("advapi32.dll", SetLastError = true)]
        private static extern bool LogonUser(
          string principal,
          string authority,
          string password,
          LogonSessionType logonType,
          LogonProvider logonProvider,
          out SafeUserTokenHandle token);

        public enum LogonSessionType : uint
        {
            Interactive = 2,
            Network,
            Batch,
            Service,
            NetworkCleartext = 8,
            NewCredentials
        }

        private enum LogonProvider : uint
        {
            Default = 0, // default for platform (use this!)
            WinNT35,     // sends smoke signals to authority
            WinNT40,     // uses NTLM
            WinNT50      // negotiates Kerb or NTLM
        }

    #endregion

    #region SafeTokenHandle Class

        [SuppressUnmanagedCodeSecurity, 
         HostProtection(SecurityAction.LinkDemand, MayLeakOnAbort=true)]
        private sealed class SafeUserTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
        {
            internal SafeUserTokenHandle() : base(true) { }

            internal SafeUserTokenHandle(IntPtr existingHandle, bool ownsHandle) : 
                base(ownsHandle)
            {
                base.SetHandle(existingHandle);
            }

            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success), 
             DllImport("kernel32.dll", SetLastError=true, ExactSpelling=true)]
            private static extern bool CloseHandle(IntPtr handle);

            protected override bool ReleaseHandle()
            {
                return CloseHandle(base.handle);
            }
        }

    #endregion
}
.NET 3.5 | C#
Monday, January 19, 2009 3:28:11 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Friday, January 02, 2009

While reading CLR via C# I picked up a couple of interesting tidbits about the using block that I never realized. First you can declare/instantiate multiple objects as long as they are of the same type and second you can pass in objects that have been declared outside the block. Not sure how useful these would be but interesting none the less. I think more useful would be allowing the developer to declare/instantiate multiple objects of different types.

class Program
{
    static void Main(string[] args)
    {
        Stuff stuff = new Stuff();

        using (
            Stuff stuff1 = new Stuff(),
            stuff2 = new Stuff(),
            stuff3 = stuff)
        {
        }
    }
}

class Stuff : IDisposable
{
    #region IDisposable Members

        public void Dispose() { }

    #endregion
}
.NET | .NET 3.5 | C#
Friday, January 02, 2009 10:23:04 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [1]  |  Trackback
Tuesday, November 18, 2008

One thing I really love about Linq is how succinctly you can write import and export code. I've had to do this many times before Linq and it always felt kludgy no matter how clean you did it (Especially building xml documents). I think the decision to bake a set based syntax into C# and VB.NET was a great idea. So here is yet another Linq code sample, aren't there already a million of them out there??

Exporting data from a SQL Server table to xml using Linq2Sql and Link2Xml:

TestDataContext dataContext =
    new TestDataContext(@"Data Source=localhost;
        Initial Catalog=Test;Integrated Security=True");

XDocument export = new XDocument(
    new XElement(
        "clients",
            new XComment("This is a comment!"),
            from client in dataContext.Clients
            orderby client.State, client.City 
            select new XElement(
                "client",
                    new XAttribute("id", client.Id.ToString()),
                    new XElement("name", new XText(client.Name)),
                    new XElement("address", new XText(client.Address)),
                    new XElement("address2", new XText(client.Address2)),
                    new XElement("city", new XText(client.City)),
                    new XElement("state", new XText(client.State)),
                    new XElement("zip", new XText(client.Zip)),
                    new XElement("comments", new XCData(
                        string.Format("{0} is based out of {1}.", 
                        client.Name, client.State)))
                )
            )
        );
export.Save(@"D:\Temp\Clients.xml");

Importing data from an xml document to a SQL Server table using Linq2Xml and Linq2Sql (And as Anon pointed out we can do a direct cast since the XAttribute (And XElement) class define explicit conversion operators for primitive types. On that note we also dont need to check if the XElement or XAttribute is null. The Linq2Sql entity defines fields (Or properties) as nullable types and the XElement and XAttribute classes define conversion operators for nullable primitive types. So if an attribute or element does not exist the entity value is simply set to null.):

TestDataContext dataContext =
    new TestDataContext(@"Data Source=localhost;
        Initial Catalog=Test;Integrated Security=True");

XDocument document = XDocument.Load(@"D:\Temp\Clients.xml");

var clients = from client in document.Element("clients").Elements("client")
    select new Client()
    {
        Id = (int)client.Attribute("id"),
        Name = (string)client.Element("name"),
        Address = (string)client.Element("address"),
        Address2 = (string)client.Element("address2"),
        City = (string)client.Element("city"),
        State = (string)client.Element("state"),
        Zip = (string)client.Element("zip")
    };

foreach (var client in clients)
    dataContext.Clients.InsertOnSubmit(client);

dataContext.SubmitChanges();
Tuesday, November 18, 2008 2:10:56 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [2]  |  Trackback
Saturday, July 26, 2008

I'm working on a media center application right now that I want to run kiosk style; topmost and fullscreen. This is amazingly simple to do in WPF, simply set the Topmost property to true, the WindowState property to Maximized and the WindowStyle to None.

.NET | .NET 3.5 | C# | WPF
Saturday, July 26, 2008 1:21:30 AM (GMT Daylight Time, UTC+01:00)  #   |  Comments [0]  |  Trackback
Wednesday, November 21, 2007

Got VS2008 Team System up and running... Only issues I ran into were needing to update the .NET Compact Framework 2.0 to SP1 and reinstalling the .NET Framework 3.0 Redist (I had this installed but something got hosed so I had to reinstall it). I ran the beta versions on a VM so I didn't have to deal with issues resulting from uninstalling betas on my dev box. I'm really liking the VM approach for evaluation! 

Rick Strahl has some interesting comments on the VS2008 install here.

Wednesday, November 21, 2007 7:00:41 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Wednesday, November 14, 2007

I guess this is a known issue with the following exception:

Unhandled Exception: System.IO.FileLoadException: Could not load file or assembly 'svcutil, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. Strong name validation failed. (Exception from HRESULT: 0x8013141A)
File name: 'svcutil, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' ---> System.Security.SecurityException: Strong name validation failed. (Exception from HRESULT: 0x8013141A)
The Zone of the assembly that failed was:
MyComputer

As a temporary fix you can mark the assembly to be skipped for strong name validation as follows:

sn.exe -Vr svcutil.exe

image

Wednesday, November 14, 2007 7:22:13 PM (GMT Standard Time, UTC+00:00)  #   |  Comments [0]  |  Trackback
Creative Commons License