Write WCF output to document - c#

Hi I have a WCF service which is working good. for testing purpose to QC the data i would like to seriliaze the data and write it to an xml document. how can this be done.
please find the below code where im consuming the WCF service in a client app
Client.EMPServiceClient proxy = new Client.EMPServiceClient();
proxy.ClientCredentials.UserName.UserName = "testuser";
proxy.ClientCredentials.UserName.Password = "password";
Client.EMPSearchCriteria criteria = new Client.EMPSearchCriteria();
criteria.EMPNumber = "01-351";
proxy.GetEMPData(criteria);
Console.Write("Finish");
I wrote a class as below to write the output to a doc - but could some one tell me how to bridge these
public static void SerializeToXML(EMPData pdata)
{
XmlSerializer serializer = new XmlSerializer(typeof(EMPData));
TextWriter txtwriter = new StreamWriter(#"d:\test.xml");
serializer.Serialize(txtwriter, pdata);
txtwriter.Close();
}
Please advice on how to write the output to an xml doc
Thanks,
Justin

Doesn't
proxy.GetEMPData(criteria);
return something? Shouldn't you use that result?
Try...
Client.EMPServiceClient proxy = new Client.EMPServiceClient();
proxy.ClientCredentials.UserName.UserName = "testuser";
proxy.ClientCredentials.UserName.Password = "password";
Client.EMPSearchCriteria criteria = new Client.EMPSearchCriteria();
criteria.EMPNumber = "01-351";
var data = proxy.GetEMPData(criteria); // Change this line
SerializeToXML(data); // and adding this line
Console.Write("Finish");

The right way to do this is with WCF's built-in message logging- no need to modify the app at all. This way, you're sure to get exactly the same message- otherwise your client's serialization can be affected by WCF configuration that won't apply when you serialize the message manually.
http://msdn.microsoft.com/en-us/library/ms751526.aspx

Related

Cannot update read/write attributes of UserPoolClient via C# SDK

When programmatically creating a Cognito user pool and app client, if the app client is to have read/write access to attributes of the user pool, that access must be explicitly given. I have been able to do so successfully for custom attributes but built-in attributes always return an error of "Invalid write attributes specified while creating a client" or "Invalid read attributes specified while creating a client".
Documentation is ... both voluminous and difficult to find. I have yet to see an example of this or an actual bit of useful documentation on the CreateUserPoolClientRequest type that says anything about this other than things like "ReadAttributes is a list of strings that are the attributes that can be read".
Here is the code I'm using that always ends up with that error message and failure to create the app client. _client is an AmazonCognitoIdentityProviderClient properly instantiated and credentialed and running in a lambda function.
var request = new CreateUserPoolClientRequest { UserPoolId = userPoolId, ClientName = $"{name}AppClient" };
var builtInAttributes = new List<string>()
{
"address","birthdate","email","family name","gender","given name","locale","middle name","name","nickname","phone number", "picture","preferred username","profile","zoneinfo","updated at","website"
};
var readAttributes = new List<string>();
var writeAttributes = new List<string>();
readAttributes.InsertRange(0,builtInAttributes);
writeAttributes.InsertRange(0, builtInAttributes);
var attributeConfig = ConfigurationHelper.GetListFromSection("UserPoolCustomAttributes");
foreach (var attribute in attributeConfig)
{
readAttributes.Add($"custom:{attribute.Key}");
writeAttributes.Add($"custom:{attribute.Key}");
}
request.ReadAttributes = readAttributes;
request.WriteAttributes = writeAttributes;
var result = await _client.CreateUserPoolClientAsync(request, CancellationToken.None);
Any help is greatly appreciated.
Figured it out. Though I have yet to find it documented anywhere, default attributes with a space in the name in the ui need to have that space replaced with an underscore when using their name in the api.

Running a TuesPechkin converter more than once

I'm using TuesPechkin for my web application, which I'm testing locally on IIS with VS2013. The user clicks a button and the page's current HTML is saved to a PDF file, which is then emailed out. This process is going to be run regularly as the site's data changes.
When converter.Convert(document) first runs, it converts without problem. Every subsequent attempt, however, results in the process hanging and me needing to restart VS.
Below is some default code I've been using to test.
public void MakePDF()
{
var document = new HtmlToPdfDocument
{
GlobalSettings =
{
ProduceOutline = true,
DocumentTitle = "Pretty Websites",
PaperSize = PaperKind.A4, // Implicit conversion to PechkinPaperSize
Margins =
{
All = 1.375,
Unit = TuesPechkin.Unit.Centimeters
}
},
Objects = {
new ObjectSettings { HtmlText = "<h1>Pretty Websites</h1><p>This might take a bit to convert!</p>" }
}
};
IConverter converter =
new ThreadSafeConverter(
new PdfToolset(
new Win32EmbeddedDeployment(
new TempFolderDeployment())));
byte[] result = converter.Convert(document);
}
Can anyone point me in the right direction on this? Most of my troubleshooting so far has led to some discussions on threading and pooling, but no concrete code solutions for running TuesPechkin more than once.
Have you tried the ThreadSafeConverter? The StandardConverter is only suitable for small console apps.
IConverter converter =
new ThreadSafeConverter(
new RemotingToolset<PdfToolset>(
new Win32EmbeddedDeployment(
new TempFolderDeployment())));
byte[] result = converter.Convert(document);
Note that you should keep the converter somewhere static, or as a singleton instance (as mentioned here).
Since this app on IIS, could get singleton converter, and use RemotingToolset
var toolSet = new RemotingToolset<PdfToolset>(winAnyCpuEmbeddedDeployment);
// Then
using TuesPechkin.Wkhtmltox.AnyCPU;
...
var converter = PDFHelper.Factory.GetConverter();
var result = converter.Convert(This.Document);
Reference : https://github.com/tloy1966/TuesPechkin

Create SOAP envelope programmatically with C#

I have this Java code:
MessageFactory factory = MessageFactory.newInstance();
SOAPMessage message = factory.createMessage();
SOAPBody body = message.getSOAPBody();
QName qualifiedName = new QName("http://mysite.com.br/",
"getQuantidade", "ns2");
SOAPBodyElement element = body.addBodyElement(qualifiedName);
SOAPElement codigoProduto = element.addChildElement(new QName("codigo"));
codigoProduto.setValue("ARQ");
SOAPElement quantidade = element.addChildElement(new QName("quantidade"));
quantidade.setValue("2");
message.writeTo(System.out);
I'd like to do the same thing in C#: mount a SOAP envelope steb by step using classes. I did some research and didn't find anything like this.
What would be the best way to do it?
I don't want the exact code as answer, just point me the way (:
Thank you very much.

How to use Soap extensions at client application

I crate one webservice using c#.For encrypting response, using the dll specified in this article
http://highcoding.blogspot.in/
WebMetod
[WebMethod]
[EncryptionExtension(Decrypt = DecryptMode.None, Encrypt = EncryptMode.Response, Target = Target.Body)]
[TracingExtension(TracingMode = TracingMode.Response, MethodName = "HelloWorld")]
public string HelloWorld() {
return "Hello World";
}
I created one webservice client using c# windows application.
ServiceReference1.ServiceSoapClient ob = new WindowsFormsApplication2.ServiceReference1.ServiceSoapClient();
string st = ob.HelloWorld();
Here i getting an error "End element 'Body' from namespace 'http://schemas.xmlsoap.org/soap/envelope/' expected"
Encryption is working.But i tried and dont able to find out a way to decrypt data at client side .Anyone know how to handle this in client?
At your proxy client code, add the 'EncryptionExtension' attribute to HelloWorld method
[EncryptionExtension(Decrypt = DecryptMode.Response, Encrypt = EncryptMode.None, Target = Target.Body)]
public string HelloWorld()
{
object[] results = this.Invoke("HelloWorld", new object[] { });
return ((string)(results[0]));
}
BEWARE, this proxy is auto-generated code. Every time you make changes to the webservice, it will be regenerated and your changes will be lost.
Best way to handling this situation is configuration soap extension through configuration. Please follow this link on how to do it.
http://fluentbytes.com/applying-soap-extension-client-proxy-without-altering-generated-proxy-code/

How to deserialize WCF message using OperationContract

I succeeded in building a WCF client generated by svcutil.exe from the WSDL. Using the generated client proxy class I can call the web service of an external service supplier. I also succeeded in coding a message inspector, as I need to log both raw XML request and response as full SOAP message to the database.
For an emergency scenario I also need to be able to "import" a raw XML response. I found many hints on using XMLSerializer or deserializing WCF messages based on the message contract.
But how can I deserialize a raw XML response based on an operation contract? For a first test I use one of the logged raw responses, save it to a file and now try to deserialize it to the response type as generated in the client proxy. Somehow I must succeed in calling DeserializeReply() from class ClientOperation. But how to get there?
I happily accept any help as I'm quite new to WCF...
TIA,
Stefan
This is what I tried after Marc's answer:
public static RatingResult DeserializeResponseFromFile(string path)
{
var xmlReader = XmlReader.Create(path);
var message = Message.CreateMessage(xmlReader, int.MaxValue, MessageVersion.Soap11);
var readerAtBodyContents = message.GetReaderAtBodyContents();
var dcs = new DataContractSerializer(typeof(RatingResult), "RatingResponse", "http://rating.webservice.xxx.de");
// Error in line 6 position 7. 'EndElement' 'RatingResponse' from namespace
// 'http://rating.webservice.xxx.de' is not expected.
// Expecting element 'commonDataField'.
var wsResult = (RatingResult)dcs.ReadObject(readerAtBodyContents);
return wsResult;
}
This is part of the logged XML response file, that I'm trying to deserialize to type RatingResponse:
<soapenv:Envelope xmlns:soapenv="..." xmlns:soapenc="..." xmlns:xsd="..." xmlns:xsi="...">
<soapenv:Header soapenv:encodingStyle="..." />
<soapenv:Body soapenv:encodingStyle="...">
<p933:RatingResponse xmlns:p933="http://rating.webservice.xxx.de">
<RatingReturn href="#id0" />
</p933:RatingResponse>
<multiRef id="id0" soapenc:root="0" soapenv:encodingStyle="..." xsi:type="p878:RatingResult" xmlns:p878="http://output.rating.webservice.xxx.de">
<commonData href="#id1" />
<acctData href="#id2" />
<resultData href="#id3" />
</multiRef>
<multiRef id="id1" soapenc:root="0" soapenv:encodingStyle="..." xsi:type="p719:RatingCommonData" xmlns:p719="http://input.rating.webservice.xxx.de">
<requestdate xsi:type="xsd:dateTime">2010-12-24T09:45:09.531Z</requestdate>
...
I guess that the data contract serializer has problems deserializing the href's. Please note that the message I try to deserialize "by hand" was captured using my injected message inspector. In a "normal" call of the web service this message get deserialized without problems.
I don't really understand what you're trying to ask and to do.... based on an operation contract ?? The operation contract is just an attribute you put on an operation / method call to mark it as a service method .... the operation contract doesn't do anything even remotely involved with serialization or deserialization..... do you mean how to deserialize an XML message using the DataContractSerializer which is the WCF default serializer??
Assuming you do really mean HOWTO: deserialize a WCF message using the DataContractSerializer, then try this: if you have the response XML from a service call that used the default WCF DataContractSerializer, you should be able to deserialize it like this (assuming you have your XML serialized response in a xmlResponse variable):
using(MemoryStream memStm = new MemoryStream())
using(StreamWriter stw = new StreamWriter(memStm))
{
// write your response to the memory stream
stw.Write(xmlResponse);
stw.Flush();
// "reset" memory stream
memStm.Seek(0, SeekOrigin.Begin);
// setup DataContractSerializer
DataContractSerializer dcs = new DataContractSerializer(typeof(YourDataType));
// deserialize result XML into an instance of "YourDataType"
var result = dcs.ReadObject(memStm);
}
For anyone in the future doing this. I had to manually read a WCF message out of the MSMSQ, and get the request object out of the MSMQ/WCF message envelope. Here's how:
Root code:
var q = new MessageQueue(#".\Private$\VishalQ;poison");
var allMessages = q.GetAllMessages().ToList();
var wcfRequests = allMessages.Select(ConvertToWcfRequest<ObjectChangedRequest>);
My contract:
[ServiceContract]
public interface IWish
{
[OperationContract(IsOneWay = true)]
void ObjectChanged(ObjectChangedRequest request);
}
My Data Contract:
[DataContract(Namespace = "http://x.namespaces.x-x.com/")]
public class ObjectChangedRequest
{
[DataMember]
public OperationType OperationType { get; set; }
}
My message deserialization code:
/// <summary>
/// Converts a WCF MSMQ message to a WCF request object.
/// </summary>
public static T ConvertToWcfRequest<T>(Message msmqMessage)
{
var buffer = new byte[msmqMessage.BodyStream.Length];
msmqMessage.BodyStream.Read(buffer, 0, (int)msmqMessage.BodyStream.Length);
var envelopeStart = FindEnvelopeStart(buffer);
using var msmqStream = new MemoryStream(buffer, envelopeStart, buffer.Length - envelopeStart);
var encodingElement = new BinaryMessageEncodingBindingElement();
var wcfMessage = encodingElement.CreateMessageEncoderFactory().Encoder.ReadMessage(msmqStream, int.MaxValue);
var document = new XmlDocument();
document.Load(wcfMessage.GetReaderAtBodyContents());
var realRoot = document.FirstChild.FirstChild;
using var wcfStream = new MemoryStream();
using var xmlWriter = XmlWriter.Create(wcfStream);
realRoot.WriteTo(xmlWriter);
xmlWriter.Flush();
wcfStream.Seek(0, SeekOrigin.Begin);
var wcfSerializer = new DataContractSerializer(typeof(T), realRoot.Name, "http://tempuri.org/"); //No idea why this has to be temp uri and not our namespace...
return (T)wcfSerializer.ReadObject(wcfStream);
}
/// <summary>
/// Locates the start of a WCF message within a MSMQ message.
/// </summary>
private static int FindEnvelopeStart(byte[] stream)
{
var position = 0;
var previousByte = stream[position];
for (position = 0; position < stream.Length; position++)
{
var currentByte = stream[position];
//Some magic numbers that define the start of the WCF message envelope
if (currentByte == 0x02 && previousByte == 0x56)
break;
previousByte = currentByte;
}
return position - 1;
}

Categories

Resources