I'm writing an WCF service based on the WSDL from an old soap service. I used svcutil to generate the the service contract and made a few changes to match the site I'm hosting it on, but when I call the service from a test client, the request object is coming in as null.
The response the service is returning is also getting serialized incorrectly which I'm sure is related. But I can't figure why its not serializing and deserializing correctly.
Here's the service contract:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = ApuConstants.Namespace)]
public interface IApuService
{
[System.ServiceModel.OperationContractAttribute(Action = "*", ReplyAction = "*")]
[System.ServiceModel.XmlSerializerFormatAttribute(Style = System.ServiceModel.OperationFormatStyle.Rpc, Use = System.ServiceModel.OperationFormatUse.Encoded)]
[System.ServiceModel.ServiceKnownTypeAttribute(typeof(Part))]
[return: System.ServiceModel.MessageParameterAttribute(Name = "return")]
Brock.Web.Apu.Response check(Brock.Web.Apu.Request request);
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class Request
{
private RequestHeader headerField;
private Lookup lookupField;
/// <remarks/>
public RequestHeader header
{
get
{
return this.headerField;
}
set
{
this.headerField = value;
}
}
/// <remarks/>
public Lookup lookup
{
get
{
return this.lookupField;
}
set
{
this.lookupField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class RequestHeader
{
private string accountField;
private string idField;
/// <remarks/>
public string account
{
get
{
return this.accountField;
}
set
{
this.accountField = value;
}
}
/// <remarks/>
public string id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class Part
{
private string oemField;
private string hicField;
private string skuField;
private string descField;
private int daysField;
private string availField;
private string branchField;
private float listField;
private float netField;
private string typeField;
private string certField;
private string statusField;
/// <remarks/>
public string oem
{
get
{
return this.oemField;
}
set
{
this.oemField = value;
}
}
/// <remarks/>
public string hic
{
get
{
return this.hicField;
}
set
{
this.hicField = value;
}
}
/// <remarks/>
public string sku
{
get
{
return this.skuField;
}
set
{
this.skuField = value;
}
}
/// <remarks/>
public string desc
{
get
{
return this.descField;
}
set
{
this.descField = value;
}
}
/// <remarks/>
public int days
{
get
{
return this.daysField;
}
set
{
this.daysField = value;
}
}
/// <remarks/>
public string avail
{
get
{
return this.availField;
}
set
{
this.availField = value;
}
}
/// <remarks/>
public string branch
{
get
{
return this.branchField;
}
set
{
this.branchField = value;
}
}
/// <remarks/>
public float list
{
get
{
return this.listField;
}
set
{
this.listField = value;
}
}
/// <remarks/>
public float net
{
get
{
return this.netField;
}
set
{
this.netField = value;
}
}
/// <remarks/>
public string type
{
get
{
return this.typeField;
}
set
{
this.typeField = value;
}
}
/// <remarks/>
public string cert
{
get
{
return this.certField;
}
set
{
this.certField = value;
}
}
/// <remarks/>
public string status
{
get
{
return this.statusField;
}
set
{
this.statusField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class ResponseHeader
{
private string statusField;
private string reasonField;
private string accountField;
private string idField;
/// <remarks/>
public string status
{
get
{
return this.statusField;
}
set
{
this.statusField = value;
}
}
/// <remarks/>
public string reason
{
get
{
return this.reasonField;
}
set
{
this.reasonField = value;
}
}
/// <remarks/>
public string account
{
get
{
return this.accountField;
}
set
{
this.accountField = value;
}
}
/// <remarks/>
public string id
{
get
{
return this.idField;
}
set
{
this.idField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class Response
{
private ResponseHeader headerField;
private Part[] itemsField;
/// <remarks/>
public ResponseHeader header
{
get
{
return this.headerField;
}
set
{
this.headerField = value;
}
}
/// <remarks/>
public Part[] items
{
get
{
return this.itemsField;
}
set
{
this.itemsField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("svcutil", "4.0.30319.33440")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.SoapTypeAttribute(Namespace = ApuConstants.Namespace)]
public partial class Lookup
{
private string oemField;
private string hicField;
private int qtyField;
private string zipField;
/// <remarks/>
public string oem
{
get
{
return this.oemField;
}
set
{
this.oemField = value;
}
}
/// <remarks/>
public string hic
{
get
{
return this.hicField;
}
set
{
this.hicField = value;
}
}
/// <remarks/>
public int qty
{
get
{
return this.qtyField;
}
set
{
this.qtyField = value;
}
}
/// <remarks/>
public string zip
{
get
{
return this.zipField;
}
set
{
this.zipField = value;
}
}
}
And the Implementation:
[ServiceBehavior(Namespace = ApuConstants.Namespace)]
public class ApuService : IApuService
{
private readonly IApuServiceHandler _handler;
private readonly ISettingService _settingService;
public ApuService()
{
_handler = EngineContext.Current.Resolve<IApuServiceHandler>();
_settingService = EngineContext.Current.Resolve<ISettingService>();
}
public Response check(Request request)
{
if (Authorized(request))
return _handler.ProcessRequest(request);
return _handler.ErrorResponse("Invalid credentials");
}
protected bool Authorized(Request request)
{
if (request == null || request.header == null)
return false;
var settings = _settingService.LoadSetting<ApuSettings>(0);
if (!string.Equals(request.header.account, settings.Username, StringComparison.InvariantCultureIgnoreCase))
return false;
if (!string.Equals(request.header.id, settings.Password))
return false;
return true;
}
}
The Configuration:
<configuration>
<system.web>
<compilation targetFramework="4.5.1" />
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ApuBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
</bindings>
<services>
<service name="Apu.WebService.ApuService" behaviorConfiguration="ApuBehavior">
<endpoint address="" binding="basicHttpBinding" contract="Web.Apu.IApuService" bindingNamespace="http://www.testurl.com/apu" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
</configuration>
The request received by the service (from OperationContext.Current.RequestContext.RequestMessage):
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<s:Header xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<To s:mustUnderstand="1" xmlns="http://schemas.microsoft.com/ws/2005/05/addressing/none">http://localhost:15555/Plugins/Brock.Apu/Remote/ApuService.svc</To>
</s:Header>
<Body>
<check xmlns="http://www.testurl.com/apu">
<request>
<header>
<account>apu</account>
<id>apu001!</id>
</header>
<lookup>
<hic>323-01327</hic>
<oem>5014351AB</oem>
<qty>2</qty>
<zip>85304</zip>
</lookup>
</request>
</check>
</Body>
</Envelope>
The Response sent by the service (which is serialized incorrectly):
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<q1:checkResponse xmlns:q1="http://www.testurl.com/apu">
<return href="#id1"/>
</q1:checkResponse>
<q2:Response id="id1" xsi:type="q2:Response" xmlns:q2="http://www.testurl.com/apu">
<header href="#id2"/>
</q2:Response>
<q3:ResponseHeader id="id2" xsi:type="q3:ResponseHeader" xmlns:q3="http://www.testurl.com/apu">
<status xsi:type="xsd:string">no</status>
<reason xsi:type="xsd:string">Invalid credentials</reason>
<account xsi:type="xsd:string"/>
<id xsi:type="xsd:string"/>
</q3:ResponseHeader>
</s:Body>
</s:Envelope>
It looks like the Response
is a partial class. Is there another piece, perhaps in another file? Is that other piece serializable? Same questions for ResponseHeader
and Part
?
I usually use the [Serializable]
decorator.
There could be an issue with the keyword list on public float list
within the Part
class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With