The question is can I validate c# object against xsd without serializing this object to the xml? If yes, please give me some quick sample.
Just to give You some introduction. I got reference to the external WCF service and I got some xsd file. I got some proxy objects requests/response for this service. In the service consumer side (just class library) I would like to validate response (c# object) against provided xsd. Can I do that without serializing response to the xml?
public Response Consume(Request message)
{
try
{
ServiceClient serviceClient = new ServiceClient();
var response = serviceClient.Execute(message);
// Here I would like to validate response without serializing against xsd
return response;
}
catch (FaultException<ValidationFault> validationException)
{
throw validationException;
}
}
Related
I'm working on a WEB API application made with .NET Framework. Right now i'm working alonside a supplier to help and integrate their WEB API with our system. One of their latest change broke my code. Since i'm using RestSharp library i'm expecting the response to always correspond to a specific type of object, independently if with was a success or failure from their side.
IRestResponse<T> response = await restClient.ExecuteAsync<T>(request);
If the response is successful they will send a json response like this
{message:"", jobNr:"2312312", status:"1"}
And then they changed the code, so that if any request input was wrong they will send a list of errors, so the response will be like this:
[{code:100, message:"contact phone is wrong"},{code:101, message:"the email is not provided"}]
I don't like this approach, since i think they should give a response for errors like this:
{errorMessages:[{code:100, message:"contact phone is wrong"},{code:101, message:"the email is not provided"}]}
But since it is not in my hands. How should i deal with it? Just parse the json response and assing to different types of objects? Thanks.
Yes, the response should be parsed manually.
Assuming RestSharp is still in charge and the original API returns errors entitled with BadRequest status code, below extension tries to deserialize the content as an array of errors (a type consists of a code and a message just like mentioned in question).
public static Error[] AsErrors(this IRestResponse response)
{
var empty = new Error[] { };
try
{
return response.StatusCode == System.Net.HttpStatusCode.BadRequest
? JsonSerializer.Deserialize<Error[]>(response.Content)
: empty;
}
catch (JsonException)
{
return empty;
}
}
Considering the NormalContent is what you truly expect as response, the usage will be:
// after creating client and request ...
var response = client.Execute<NormalContent>(request);
var errors = response.AsErrors();
if (errors.Any())
{
//Deal with errors
}
else
{
//response.Data gets populated with RealResult
}
NOTE: Using the procedure as an extension depends on how common is the response pattern in your case.
I want to get an XML response from Client by using Web service.For this i am going to create a web service that can take XML , so that they can use the web service to send the XML to me.
Remember in this i have to create both ends.
Somebody please advise on this...
public XmlDocument GetXmlDocument(string pXML)
{
// Create an XmlDocument object.
XmlDocument xmlDocumentObject = new XmlDocument();
xmlDocumentObject.LoadXml(pXML);
// Return the created XmlDocument object.
return (xmlDocumentObject);
}
The above code will take take any XML as string . How could my client will use this method on there end and send the response to me.
I am looking at adding SMS abilities to my WCF service. I found a cheap SMS service called Penny SMS.
Their interface supports json. But I have no idea how to call it in my WCF service.
Here is the interface/example:
Sample JSON-RPC Request
{ "method": "send",
"params": [
"YOUR_API_KEY",
"msg#mycompany.com",
"5551231234",
"Test Message from PENNY SMS"
]
}
How would I call that with C# from a WCF service? What I am looking for is a way to wrap this into a method call. Something like:
StaticSMSClass.SendSMS("1234567890", "My Message to send");
Note they also support an XML-RPC API if that is more doable from C#.
UPDATE: I made a stab at creating a call myself, but it did not work. I am going to post my attempt in a separate question and see if anyone has a way to do it.
You need to send a HTTP POST with the JSON message to the remote server. You can do this with HttpWebRequest. You either build the JSON manually (the messages seem simple), or define types for it and use a JSON serializer.
MSDN has an example, for your case it would look something like (untested):
string json = // Your JSON message
WebRequest request = WebRequest.Create ("http://api.pennysms.com/jsonrpc");
request.Method = "POST";
var postData = Encoding.UTF8.GetBytes(json);
request.ContentLength = postData.Length;
request.ContentType = "text/json";
using(var reqStream = request.GetRequestStream())
{
reqStream.Write(postData);
}
using(var response = request.GetResponse())
{
// Response status is in response.StatusCode
// Or you can read the response content using response.GetResponseStream();
}
See my answer to the question "Client configuration to consume WCF JSON web service" for how the create a JSON client with WCF.
The answers so far are good, but one additional thing you can take advantage of (since you are within a WCF service) is the use of DataContractJsonSerializer.
In particular, I refer to how you actually populate your JSON in the first line of driis's example.
string json = // Your JSON message
Now, one of the best ways to do this may be to create a new class with these members:
[DataContract]
class SomeType
{
[DataMember]
string method;
[DataMember]
string[] params;
}
Then, just create an instance of SomeType every time and serialize it to JSON using the DataContractJsonSerializer every time you want to send over a piece of data. See http://msdn.microsoft.com/en-us/library/bb412179.aspx for how to use the DataContractJsonSerializer stand-alone.
Hope this helps!
Check the WCF REST API. They serve JSON, maybe they also can send JSON (in intra WCF solution it works). Maybe you have to construct the contract in wsdl to get the service running but maybe it works out.
I can see the object in Fiddler but the object is not deserializing on my end. Has anyone seen this before?
"Response is null" or "Response contains nulls" or "Request is null" or "Request contains null" almost always mean that you have a namespace mismatch. For instance, the response may contain:
<response xmlns="http://foo.com"/>
but should in fact be
<response xmlns="http://bar.com"/>
In this case, null will be received.
I had the same problem, and as suggested the namespace problem was the root cause.However, my proxy class has nested classes and long chain of nested namespace.
It was confusing to identify the correct namespace to apply in Cs code for proxy class. Here, i describe how to figure out the namespace which is required to be updated in client proxy.
What i did was intercept the request in ClientMessageInspector class, AfterReceiveReply method (Enables inspection or modification of a message after a reply message is received but prior to passing it back to the client application.) Verified the namespace of the object which were returning null in Response by using XMLDocument. I updated the proxy class with the namespace retreived from XML. After making the changes, the objects were not null in response.
public class MyMessageInspector : IClientMessageInspector
{
public void AfterReceiveReply(ref System.ServiceModel.Channels.Message request, object correlationState)
{
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms);
request.WriteMessage(writer);
writer.Flush();
ms.Position = 0;
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(ms);
this.ReadMessage(xmlDoc);
ms = new MemoryStream();
xmlDoc.Save(ms);
ms.Position = 0;
XmlReader reader = XmlReader.Create(ms);
Message newMessage = Message.CreateMessage(reader, int.MaxValue, request.Version);
newMessage.Properties.CopyProperties(request.Properties);
request = newMessage;
}
private void ReadMessage(XmlDocument xmlDoc)
{
XmlNode v1 = xmlDoc.GetElementsByTagName("XPAth");
//Actual Namespace in XML, which should be used in Proxy Class
string namespaceURIForObjectInXML = v1.NamespaceURI;
}
public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel)
{
}
}
I had a similar case where I created a client via SVCUTIL / Service Reference from VS. The response was received successfully with correct data (confirmed via IClientMessageInspector.AfterReceiveReply method) however the values at the object level were not being populated. There were no de-serialization errors (confirmed via system.diagnostics output)
The problem was twofold:
1) Certain objects were named exactly as their types but had different namespaces from their types. This seems to have confused the proxy generator in assigning the namespace parameter (in the System.Xml.Serialization.XmlElementAttribute annotation) of the class to the one of the object
2) The order parameter (in the System.Xml.Serialization.XmlElementAttribute annotation) of the properties was not required and also the namespace parameter was missing
so from: [System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Order=0)]
to: [System.Xml.Serialization.XmlElementAttribute(IsNullable=true, Namespace="http://www.whathevernamespaceiscorrect.com")]
So basically, in the generated proxy I needed to fix the namespace of the class to the one specified in the type, and replace the order parameter with the namespace parameter setting it to the correct namespace according to the wsdl
The only reason I can think of is a contract mismatch. Although it's strange if no validation error is thrown. Are you using a client generated from the correct WSDL? Is it a WCF client or a SOAP one? The former one does validation, I'm sure, but schema mismatches may slip through the latter.
Every time this happens to me, it's because I need to update my service references. Try that and let me know what happens :)
Solved it... or at least have workaround. In the Java code the #XmlElementRefs and #XmlElementRef should have been #XmlElements and #XmlElement respectively (as well as the "type" attribute it needed a "name" attribute).
Guessing if I'd posted this as a new question with a Java tag as well as C# and web-services some hawk-eyed stackoverflower would have spotted this schoolboy error.
I had a similar issue which i resolved by checking the Order value in the Reference.cs.
[System.Xml.Serialization.XmlElementAttribute(Order=0)]
The order of the return parameters had changed but updating my service reference in visual studio didn't change the "Order" value.
Check that parameters returned in Fiddler/SoapUI are the same as in your proxy generated class.
Ensure the definition / specification matches the output. Compare the WSDL (in browser) and the response (in SOAP-UI, Fiddler), e.g.
WSDL uses camel case (lastName) and
response uses underscores (last_name).
I'd like my WCF service to return an xml file that has been signed.
I found documentation that shows how to sign an XmlDocument on msdn, but since a WCF function can't return an XmlDocument I'm not sure if the following would work (similar to thisquestion)
public XmlElement GetXml() {
var doc = new XmlDocument();
// add data to doc
// sign doc
return doc.DocumentElement;
}
Would it still be possible to verify the signature of doc.DocumentElement if I added it to another XmlDocument after a client requested it? Is there a better way to do this?
Thanks!
XmlDocument is not decorated with DataContractAttribute and I cannot see why the object needs to be sent over the wire while the serialized form (text form) is all that is required.
I would design it as:
[OperationContract]
string GetFooXml();
And send the string. That is what WCF/XML is for, sending data as text whenever possible so that more kinds of clients can consume it.