Entity Design for web service - entity

My client will be sending the request as described below in SOAP format.
<RequestTimestamp>2014-08-22T11:28:00Z</RequestTimestamp>
<SystemID>TestProcessor</SystemID>
<Version>1<Version>
<QWID>201507080000001</QWID>
<QWID>201507080000010</QWID>
<QWID>201507080000001</QWID>
<QWID>201507080000010</QWID>
<QWID>201507080000001</QWID>
<QWID>201507080000010</QWID>
<CHL>201507080000010</CHL>
In every request, QWID should come as batch and I proposed below entity design to adopt above data.
public class APIRequest
{
[DataMember]
public DateTime RequestTimestamp;
[DataMember]
public string SystemID;
[DataMember]
public int Version;
[DataMember]
public string[] QWID;
[DataMember]
public string CHL;
}
With above entity design, SOAP request generated as
<request xmlns:a="http://schemas.datacontract.org/2004/07/QWID.Services" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<a:RequestTimestamp>0001-01-01T00:00:00</a:RequestTimestamp>
<a:SystemID>WireSystem_001</a:SystemID>
<a:Version>0</a:Version>
<a:QWID xmlns:b="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
<b:string>20141023010232_ORG99000002_CTR.fedwire</b:string>
<b:string>20141023010842_ORG99000001_CTR.fedwire</b:string>
</a:QWID>
</request>
My client expecting the SOAP request in the form of <QWID>201507080000001</QWID> instead of coming under <QWID><b:string>20141023010232_ORG99000002_CTR.fedwire</b:string> </QWID> as string tag.
How do i do the entity design (without grouping of QWID) to achieve client expectation as described above? Please help me on this?

Related

How to serialize complex model to xml format wcf

I am developing a wcf application which is taking c# request model as an input and returning complex response c# model after populating data in it from database. I am using SOAP UI client tool to test my service.
Earlier i had decorated my contract with XmlSerializerFormat attribute and after submitting request i was able to get the response in Result tab of SOAP UI tool. Below is the code snippet of it :
[ServiceContract]
[XmlSerializerFormat]
public interface IService1
{
[OperationContract]
Employee GetData(Employee value);
}
[DataContract]
public class Employee
{
[DataMember]
public int Id { get; set; }
[DataMember]
public string Name { get; set; }
public string Address { get; set; }
}
But now due to some reasons i have removed XmlSerializerFormat attribute from contract and i want default serializer to take care of it. But when i am submitting the request from client , my response model is populating with results but Response tab of SOAP UI shows empty response.
During Response model population when i am removing certain properties from response model, i am able to see result in response tab of SOAP UI tool.
Is Default serializer in facing some issues while serializing some of property of my model. Any other attribute apart from XmlSerializerFormat ?
Please let me know where i am lacking or is there any alternative of XmlSerializerFormat attribute.
Thnx in Advance
Try adding DataContract attribute to the Employee on the class level and DataMember attribute to its properties that you want to be serialized. If it has complex property types of its own they also may need to be decorated similarly. Default serializer in WCF is DataContract serializer FYI.

WCF DataContract Attribute

I have a question about the [DataContract] attribute.
I have written my code like below: here I am not using [DataContract] attribute for my test class.
class test
{
[Datamember]
public string Strproperty
{
get;
set;
}
[Datamemer]
public string Strproperty2
{
get;
set;
}
}
class checktotal:Iservice
{
public string testmethod(test obj)
{
return obj.Strproperty+Strproperty2;
}
}
For that I am sending data from client I am getting the values correctly.
Here is it necessary to use [DataContract] attribute for that test class?
If I removed [Datamember] for test class property is getting error while sending from client. But I am not getting any errors even if I am not using the [DataContract] attribute.
Please give me a brief explanation with example so that I can understand when to give that attribute and when do not give that attribute.
Thanks,
Satya Pratap.
The DataContractSerializer can deal with classes that do not have the DataContract attribute if they provide a default constructor. See the MSDN documentation for more details.
As of .NET 3.5 Service Pack 1, you can omit (not use) the [DataContract] and [DataMember] attributes. If you do that, then the DataContractSerializer in WCF will behave just like the XML serializer - it will serialize all public properties only.
I prefer to use [DataContract] and [DataMember] explicitly anyway - it gives me the opportunity to specify options (like the data contract's XML namespace, the order of the [DataMember]) and it lets me e.g. also exclude certain properties from serialization.
As soon as you start using [DataMember] on one property, then only those properties decorated with a [DataMember] will be looked at for the WCF serialization.

wcf serialisation

Fairly new to WCF and need help with understanding why serialisation is not working correctly.
Service definition - I just want to post, serialise into a LogDeviceCommunication object and then just return the object as a simple test
[OperationContract]
[WebInvoke(UriTemplate = "AddDeviceCommunicationLog", RequestFormat =
WebMessageFormat.Xml, BodyStyle = WebMessageBodyStyle.Bare, Method = "POST")]
LogDeviceCommunication AddDeviceCommunicationLog(LogDeviceCommunication
deviceCommunicationEntry);
public LogDeviceCommunication AddDeviceCommunicationLog(LogDeviceCommunication
deviceCommunicationEntry)
{
return deviceCommunicationEntry;
}
At the moment I am just posting the following XML with Fiddler as a test.
<?xml version="1.0" encoding="UTF-8"?>
<LogDeviceCommunication>
<ID>1207a26e-ab59-4977-b7eb-b2776205cffe</ID>
<DeviceID>A42E8707-7C65-45AA-8E58-5D21F53DA101</DeviceID>
<Time>2012-03-14T15:38:28.379Z</Time>
<Line>0</Line>
<Tab>0</Tab>
<Info>Starting Synchronisation</Info>
</LogDeviceCommunication>
Results returned from Fiddler
<LogDeviceCommunication z:Id="i1" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"
xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/">
<ChangeTracker z:Id="i2"
xmlns:a="http://schemas.datacontract.org/2004/07/conxEntities">
<a:ExtendedProperties/>
<a:ObjectsAddedToCollectionProperties/>
<a:ObjectsRemovedFromCollectionProperties/>
<a:OriginalValues/>
<a:State>Added</a:State>
</ChangeTracker>
<DeviceID>00000000-0000-0000-0000-000000000000</DeviceID>
<ID>1207a26e-ab59-4977-b7eb-b2776205cffe</ID>
<Info i:nil="true"/>
<Line i:nil="true"/>
<Tab i:nil="true"/>
<Time>2012-03-14T15:38:28.379Z</Time>
</LogDeviceCommunication>
Why does the DeviceID contain the 0000's (I assume it's a null Guid) while the ID contains the correct Guid; also why do the Info, Line and Info elements contain nil values?
The LogDeviceCommunication is a POCO generated from EF4 using the ADO.NET Self Tracking Template
Condensed version is
[DataContract(IsReference = true, Namespace = "")]
public partial class LogDeviceCommunication: IObjectWithChangeTracker,
INotifyPropertyChanged
[DataMember]
public System.Guid DeviceID
[DataMember]
public System.DateTime Time
[DataMember]
public Nullable<int> Line
[DataMember]
public Nullable<int> Tab
[DataMember]
public string Info
[DataMember]
public System.Guid ID
I am sure I am doing something incorrectly so any help appreciated.
The problem lies in the required ordering of the XML.
WCF Datacontract, some fields do not deserialize
http://neimke.blogspot.co.nz/2012/03/serialization-ordering-causes-problems.html
When WCF receives your request, its deserialization machinery will create a new instance of the LogDeviceCommunication type to populate with the values it receives. It seems that the code from the EF partial class of your instance is being triggered and it results in what you post in your question.
Try setting a debugger break point on the return statement in your AddDeviceCommunicationLog method to see what EF & WCF deserialized for you. If it's just as what you posted then the issue is likely caused by the EF plumbing code. Also, you may want to enable WCF message tracing to see what WCF is actually receiving and sending back.
EDIT: Just ran across this blog post that shows some of the interaction between EF & WCF. You may want to review it to see if it's applicable to your issue.
I bet the other parts of the class, generated by that template, include the elements you're seeing.
In general, it's not a good idea to return EF entities (or any complex .NET type) from a web service - they drag along implementation dependencies. Return a purely POCO class as a DTO instead.

WCF 4: Passing Empty parameters on a GET request

I'm creating an API which will just use a get request to return some search results from the database, I'm trying to make it so that optional parameters can be passed (easy with WCF) but also so that if parameters are specfied in the query string as long as they are empty they will be ignored by the service.
However if you have the a query string with empty parameters it will return a bad request (400) by the server e.g.
Using a end-user point of your choice pass the following querystring
http://www.exampleservice.com/basic/?apiKey=1234&noOfResults=3&maxSalary=&minSalary=&ouId=0&keywords=Web+Developer
Note that maxSalary and minSalary are not passing values
You then have the following WCF service:
[OperationContract]
[WebGet(UriTemplate = "basic/?apiKey={apiKey}&noOfResults={noOfResults}&maxSalary={maxSalary}&minSalary={minSalary}&ouId={ouId}&keywords={keywords}", BodyStyle = WebMessageBodyStyle.Bare)]
public List<SearchResultsDto> BasicSearch(string keywords, string apiKey, int noOfResults, int maxSalary, int minSalary, int ouId)
{
//Do some service stuff
}
This will cause a 400 error, please can someone explain how you pass empty parameters across to a WCF service or is this just not possible?
Currently passing null or an empty parameter is not supported in WCF, the main solution to this problem is to override the querystringconverter which handles the url as it comes through the pipe but before it reaches the operation contract.
An excellent example of implmenting an extension of the querystringconverter is found here:
In the WCF web programming model, how can one write an operation contract with an array of query string parameters (i.e. with the same name)?
HOWEVER
sadly there is a bug in WCF 4 where you cannot override the querystringconverter, this has been addressed by Microsoft and will be fixed in the SP1 release coming this year.
Until then there is no clean way to deal with this situation other than to handle the exception and return a status code of 400 (bad request) - good documentation of the api should handle this in the interim.
Is it just the integers giving you trouble? Maybe you can try making them nullable?
int? MaxSalary
hope this helps
You could send in "-1", and treat that in your business logic as not sent.
It can be handled in multiple ways. Since you are talking about a REST service that can have optional parameters, my suggestion will be do the something like this.
Create a DataObject that will be accepeted as parameter to this method.
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(RequestFormat=WebMessageFormat.Json)]
RequestObject BasicSearch(RequestObject apiKey);
}
public class Service1 : IService1
{
public RequestObject BasicSearch(RequestObject obj)
{
//Do some service stuff
return obj;
}
}
[DataContract]
public class RequestObject
{
[DataMember]
public string Keywords {get; set;}
[DataMember]
public string ApiKey {get; set;}
[DataMember]
public int NoOfResults { get; set; }
}
Advantages (am going to be short, ping me back for details)
No change in service signature
contract does not change
you will get the flexibility of have
null parameters
you can always extend the number of
parameters without any impact to
existing services
below is the sample input and output from fiddler
note: in the request part i havent passed anything to NumberOfResults intentionally to prove

How do you send complex objects using WCF? Does it work? Is it good?

Can I have a data contract of this shape??
[DataContract]
public class YearlyStatistic{
[DataMember]
public string Year{get;set;}
[DataMember]
public string StatisticName {get;set;}
[DataMember]
public List<MonthlyStatistic> MonthlyStats {get;set}
};
I am assuming here that class MonthlyStatistic will also need to be a DataContract. Can you do this in a web service?
To use the same model for web services, mark your class as Serializable use the XmlRoot and XmlElement in the System.Xml.Serialization namespace. Here is a sample using your example:
[Serializable]
[XmlRoot("YearlyStatistic")]
public class YearlyStatistic
{
[XmlElement("Year")]
public string Year { get; set; }
[XmlElement("StatisticName")]
public string StatisticName { get; set; }
[XmlElement("MonthlyStats")]
public List<MonthlyStatistic> MonthlyStats { get; set; }
}
You will have to do the same thing for your complex object properties of the parent object.
Yep, thats standard WCF serialization right there. Are you trying to say the MonthlyStats collection has a property called WeeklyStats, or that each individual MonthlyStatistic has a WeeklyStat collection? If its the former, that doesnt work in WCF natively. You will have to do some fiddling in order to get it to work. If its the latter, its perfectly fine.
Yes, you can send the data contract you mentioned above back and forth from a WCF service. Like you said, MonthlyStatistic and all its members will have to be defined as data contracts themselves or be built in types (like strings).
You can even send and receive more complex types like when you have a base class but want to send or receive an object of a derived class (you would do that using the KnownType attribute). While receiving (de-serialization), from Javascript, there's a trick using which you have to specify the type for WCF. If you are interested, feel free to ask.