Search code examples
c#wcfjanrain

Problem communicating with Janrain "auth_info" service in WCF


So I'm stuck at this point. I am trying to communicate with JanRain's "auth_info" service. In fact, to start, I'm just trying to get the "error" message/object/'.jsthingy' that you get when you surf to it directly in the browser:

https://rpxnow.com/api/v2/auth_info

but I want to get that back with a WCF call.

According to Fiddler, the content type of the information at that url is text/javascript. However, from what I can tell, WCF doesn't give me that option when calling it through WCF. I get two options: WebMessageFormat.Json, or WebMessageFormat.Xml.

I get the following error in Visual Studio:

InvalidOperationException was unhandled by User Code - The incoming message has an unexpected message format 'Raw'. The expected message formats for the operation are 'Xml', 'Json'. This can be because a WebContentTypeMapper has not been configured on the binding. See the documentation of WebContentTypeMapper for more details.

WTF? So can WCF even do this? (I suspect a more manual solution ahead)

JanRain's online code examples are a little bit lacking in the C# examples.

Their documentation link on auth_info is here https://rpxnow.com/docs#auth_info

The address of their auth_info service is here:

https://rpxnow.com/api/v2/auth_info

[TestMethod]
public void CallJanRain()
{
    var x = new JanRainProxy("https://rpxnow.com/api/v2");

    x.GetAuthInfo("", ""); //the params are apiKey, and token. not passing either at the moment as I want to be able to know how to at least handle the error first. After all, the *browser* at least got it.. 
}


  [ServiceContract]
    public interface IJanRainContract
    {
        [OperationContract(Name="auth_info")]
        [WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat =  WebMessageFormat.Xml)]
        JanRainAuthInfo GetAuthInfo(string apiKey, string token);
    }


 [DataContract]
    public class JanRainAuthInfo
    {
        [DataMember(Name="identifier")]
        public string Identifier { get; set; }
    }

 public class JanRainProxy: ClientBase<IJanRainContract>
    {
        public JanRainProxy(string url, WebHttpSecurityMode securityMode = WebHttpSecurityMode.Transport)
            : base(ConstructEndpoint(url, securityMode))
        {

        }


        //JanRainContract
    public JanRainAuthInfo GetAuthInfo(string apiKey, string token)
    {
         return base.Channel.GetAuthInfo(apiKey, token);
    }

    // This method constructs a WebHttpBinding endpoint with all the appropriate
    // settings for talking to our services.
    private static ServiceEndpoint ConstructEndpoint(string serviceUri, WebHttpSecurityMode securityMode)
    {
        var contract = ContractDescription.GetContract(typeof(IJanRainContract));
        var binding = new WebHttpBinding(securityMode);
                          //{
                          //    MaxBufferPoolSize = 524288000,
                          //    MaxReceivedMessageSize = 65536000
                          //};

        var address = new EndpointAddress(serviceUri);
        var endpoint = new ServiceEndpoint(
            contract,
            binding,
            address);

        var webHttpBehavior = new WebHttpBehavior()
        {
            DefaultBodyStyle = WebMessageBodyStyle.Wrapped,
            DefaultOutgoingRequestFormat = WebMessageFormat.Json,
            DefaultOutgoingResponseFormat = WebMessageFormat.Json,
            AutomaticFormatSelectionEnabled = true,
            FaultExceptionEnabled = true
        };

        endpoint.Behaviors.Add(webHttpBehavior);
        return endpoint;
    }
}

I'm figuring that perhaps I should leave the contenttype at json and tweak the behavior, or binding.


Solution

  • ok.. it looks like I needed to add a custom contentTypeMapper on my binding

    after declaring my binding I added the following:

        WebContentTypeMapper customMapper = new JsonContentTypeMapper();
        binding.ContentTypeMapper = customMapper;
    

    here's the custom Mapper:

      public class JsonContentTypeMapper : WebContentTypeMapper
        {
            public override WebContentFormat
                       GetMessageFormatForContentType(string contentType)
            {
                if (contentType == "text/javascript")
                {
                    return WebContentFormat.Raw;
                }
                else
                {
                    return WebContentFormat.Json;
                }
            }
        }