views:

17

answers:

1

I'm trying to process a post by a third party server (Paypal) processed by my server through a WCF (.Net 3.5 SP1) service. All I need is to get and process the values with the query string. This sounds incredibly easy, but after a weekend, I'm still stumped. Any help would be greatly appreciated.

Passing the following URL from my browser to the service causes a AddressFilter mismatch fault (below).

http://localhost:9409/PPInfo.svc/ReadResponse?RESULT=0&AUTHCODE=10001&RESPMSG=APROVED&PNREF=12345

produces

<Fault xmlns="http://schemas.microsoft.com/ws/2005/05/envelope/none"&gt;
- <Code>
  <Value>Sender</Value> 
- <Subcode>
  <Value xmlns:a="http://schemas.microsoft.com/ws/2005/05/addressing/none"&gt;a:DestinationUnreachable&lt;/Value&gt; 
  </Subcode>
  </Code>
- <Reason>
  <Text xml:lang="en-US">The message with To 'http://localhost:9409/PPInfo.svc/ReadResponse?RESULT=0&amp;AUTHCODE=10001&amp;RESPMSG=APROVED&amp;PNREF=12345' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree.</Text> 
  </Reason>
  </Fault>

// web.config
 <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior name="ASEEESPrivate.PPInfoBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <services>
      <service behaviorConfiguration="ASEEESPrivate.PPInfoBehavior" name="ASEEESPrivate.PPInfo">
        <endpoint address="" binding="webHttpBinding" contract="ASEEESPrivate.IPPInfo">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

================================

[ServiceContract]
public interface IPPInfo
{
    // expecting RESULT = 0 and RESPMSG = APPROVED
    [OperationContract] 
    [WebGet(UriTemplate = "Presponse?RESULT={result}&AUTHCODE={authcode}&RESPMSG={respmsg}&AVSDATA={avsdata}&PNREF={pnref}", 
        BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml)]
    void ReadResponse();
}

=================================

// write parameters of query string to tlkpOnlineMessage table
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, AddressFilterMode=AddressFilterMode.Any)]
    public class PPInfo : IPPInfo
    {

        public void ReadResponse()
        {
            var qString = HttpContext.Current.Request.QueryString;

            var ctx =
                new MembershipEntities();

            var log = new tlkpOnlineMessage();

            foreach (string s in qString)
            {
                log.LoginPageMsg = s;
                ctx.AddTotlkpOnlineMessages(log);
            }

            ctx.SaveChanges();
        }
    }
A: 

Besides the typo in your code, I believe you have two problems that are easily correctable:

1) For a RESTful service, you should define an endpoint behavior and enable the webHttp behavior. You can do this by adding an <endpointBehavior> to your web.config as such:

<behaviors>
  <serviceBehaviors>
    <behavior name="ASEEESPrivate.PPInfoBehavior">
      <serviceMetadata httpGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="true" />
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="ASEEESPrivate.PPInfoEndpointBehavior">
      <webHttp />
    </behavior>
  </endpointBehaviors>
</behaviors>

And then add this endpoint behavior to your service definition:

  <service behaviorConfiguration="ASEEESPrivate.PPInfoBehavior" name="WcfRestService1.PPInfo">
    <endpoint address="" binding="webHttpBinding" contract="WcfRestService1.IPPInfo"
              behaviorConfiguration="ASEEESPrivate.PPInfoEndpointBehavior">
      <identity>
        <dns value="localhost" />
      </identity>
    </endpoint>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>

2) Secondly, you define a UriTemplate for your service with placeholders (result, authcode, etc.) but you don't define parameters for them in your interface. If you're going to define a UriTemplate for your service definition with placeholders, then you need to have your service define those parameters accordingly. You can do that as such:

[ServiceContract]
public interface IPPInfo
{
    // expecting RESULT = 0 and RESPMSG = APPROVED
    [OperationContract]
    [WebGet(UriTemplate = "ReadResponse?RESULT={result}&AUTHCODE={authcode}&RESPMSG={respmsg}&AVSDATA={avsdata}&PNREF={pnref}",
        BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml)]
    void ReadResponse(string result, string authcode, string respmsg, string avsdata, string pnref);
}


[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, AddressFilterMode = AddressFilterMode.Any)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class PPInfo : IPPInfo
{

    public void ReadResponse(string result, string authcode, string respmsg, string avsdata, string pnref)
    {
      ...
    }
}

By using a UriTemplate, you don't need to extract your querystring parameters out; or, if you want to extract parameters from your querystring, don't define a UriTemplate.

Once I made these two changes, I was able to get the service to run locally on my machine.

I hope this helps!

David Hoerster