I’m trying to consume a webservice in .NET Core 2.0 by using SOAP. The client for the webservice was generated with the “Connected Service”-feature of Visual Studio.
Now I have the problem, that the webservice needs in the request the (first) line with the encoding-Attribute:
<?xml version="1.0" encoding="utf-8"?>
I’ve tried many different ways to write this line in the output-XML, but nothing works.
First approach:
I added a new endpoint behavior (by implementing IEndpointBehavior) to the client with using a customized message inspector (by implementing IClientMessageInspector). Via debugging I found out, the message object contains the said line. But by writing the outgoing XML to the webservice, the line is missing.
Second approach:
I wrote a customized message encoding binding element with a wsdl export extension (by using MessageEncodingBindingElement & IWsdlExportExtension) . This binding element uses a customized MessageEncoder where the encoding is set explicitly. I added the binding to the generated client.
Here are some .net 4.6 code snippets:
// Binding for the client
TextMessageBindingElement textBindingElement = new TextMessageBindingElement();
textBindingElement.Encoding = "utf-8";
textBindingElement.MessageVersion = MessageVersion.Soap11;
textBindingElement.MediaType = "text/xml";
bindingElements.Add(textBindingElement);
CustomBinding binding = new CustomBinding(bindingElements);
// Customized Message Binding Element for encoding
public class TextMessageBindingElement : MessageEncodingBindingElement,
IWsdlExportExtension {
public override MessageVersion MessageVersion { get; set; }
public string Encoding { get; set; }
...
public override MessageEncoderFactory CreateMessageEncoderFactory() {
return new TextMessageEncoderFactory(MediaType, Encoding, MessageVersion);
}
void ExportContract(WsdlExporter exporter, WsdlContractConversionContext context) {
}
void ExportEndpoint(WsdlExporter exporter, WsdlEndpointConversionContext context) {
TextMessageEncodingBindingElement mebe = new TextMessageEncodingBindingElement();
mebe.MessageVersion = this.msgVersion;
((IWsdlExportExtension) mebe).ExportEndpoint(exporter, context);
}
}
In .NET 4.6 this works, but .NET Core 2.0 doesn’t support IWsdlExportExtension. I’ve searched for alternatives, but haven’t found anything yet.
Please, can anybody help me?
Related
I have followed the following link to use a Razor style syntax with my email templates;
Microsoft Code Razorlight Tutorial
I have implemented a static helper class for getting my templates.
public static string GetTraderApplicationDeletedTemplate(Trader trader)
{
string templatePath = $#"{Directory.GetCurrentDirectory()}\EmailTemplates";
IRazorLightEngine engine = EngineFactory.CreatePhysical(templatePath);
string result = engine.Parse("TraderDeletedEmail.cshtml", trader);
return result;
}
However, when debugging the engine.Parse method is throwing a System.TypeLoadException with no further detail?
Now the templatePath is valid (as is the file name .cshtml)? Does anyone have any ideas on what could be causing this error?
I started created a Unity game as a Visual Studio project. I created a side project (WinForms) for testing as I don't know unit testing. There, all of my code works perfectly, the serialization class works flawlessly even when the protobuf-net DLL used is the one for Unity. Now, when I started to work on Unity, I copied over all of my code and DLLs for protobuf-net and MySQL.Data. For some reason, I cannot get the (basically)same code to work. I always get an exception when de-serializing, mainly this:
Invalid field in source data: 0
And this
Unexpected end-group in source data; this usually means the source data is corrupt
This is the stack trace for the last exception:
ProtoBuf.ProtoException: Unexpected end-group in source data; this usually means the source data is corrupt
at ProtoBuf.ProtoReader.ReadFieldHeader ()
at (wrapper dynamic-method) NeohumanSoftware.AoN.UserInformation.User.proto_2 (object,ProtoBuf.ProtoReader)
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader)
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader)
at ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader,System.Type,object,bool)
at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type,ProtoBuf.SerializationContext)
at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type)
at ProtoBuf.Serializer.Deserialize (System.IO.Stream) <0x000ae>
at NeohumanSoftware.AoN.Storage.SerializationHandler.DeSerialize (string) <0x00140>
at NeohumanSoftware.AoN.Storage.DataHandler.DeserializeUser (string)
I omitted the last part of the stack trace as it's not relevant. I do not understand why it works in Visual Studio but not in Unity. This is the serializer:
using (MemoryStream ms = new MemoryStream())
{
Serializer.Serialize(ms, ToSerialize);
return ms.ToArray();
}
And this is the de-serializer:
using (MemoryStream ms = new MemoryStream(ToDeSerialize))
{
return Serializer.Deserialize<T>(ms);
}
And this is the object to serialize which is the "heart" of the game as everything comes from User.user:
[ProtoContract]
internal class User
{
internal static User user { get; set; }
[ProtoMember(1)]
internal Something uSomething { get; private set; }
[ProtoMember(2)]
internal bool uSomething2 { get; set; }
[ProtoMember(3)]
internal Something3 uSomething3 { get; set; }
[ProtoMember(4)]
internal Something4 uSomething4 { get; private set; }
[ProtoMember(5)]
internal Something5 uSomething5 { get; private set; }
All of these custom classes have the [ProtoContract] attribute along with at least one [ProtoMember], and I do not use any other attribute apart from these 2. This is the flow of the game:
Data is created.
Data is serialized.
Serialized data is passed on for encryption (RijndaelManaged).
Encrypted and serialized data is written to a file.
Game ends
Data is loaded from the file.
Data is unencrypted using the exact same Key and IV (randomly generated and stored)
Data is de-serialized.
Game starts
EDIT:
Trying to use Visual Studio's project to de-serialize Unity's data does NOT work. Trying to use Unity to de-serialize Visual Studio's data does NOT work. It seems like Unity does not like protobuf-net at all...
EDIT2:
I changed the serializer method to:
byte[] b;
using (MemoryStream ms = new MemoryStream())
{
Serializer.Serialize(ms, toXML);
b = new byte[ms.Position];
var fullB = ms.GetBuffer();
Array.Copy(fullB, b, b.Length);
}
And this is what I got:
ProtoBuf.ProtoException: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see Using Protobuf-net, I suddenly got an exception about an unknown wire-type
at ProtoBuf.ProtoReader.SkipField ()
at (wrapper dynamic-method) NeohumanSoftware.AoN.UserInformation.User.proto_2 (object,ProtoBuf.ProtoReader)
at ProtoBuf.Serializers.CompiledSerializer.ProtoBuf.Serializers.IProtoSerializer.Read (object,ProtoBuf.ProtoReader)
at ProtoBuf.Meta.RuntimeTypeModel.Deserialize (int,object,ProtoBuf.ProtoReader)
at ProtoBuf.Meta.TypeModel.DeserializeCore (ProtoBuf.ProtoReader,System.Type,object,bool)
at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type,ProtoBuf.SerializationContext)
at ProtoBuf.Meta.TypeModel.Deserialize (System.IO.Stream,object,System.Type)
at ProtoBuf.Serializer.Deserialize (System.IO.Stream) <0x000ae>
If it helps, these are the read and write to file methods:
internal static void SaveUser(string userSerialized)
{
File.WriteAllText(SomePath, userSerialized);
}
internal static void LoadUser(string userSerialized)
{
File.ReadAllText(SomePath);
}
EDIT 3:
In Unity's project, I had these that I did not have in Visual Studio's project:
internal static Coordinates FromVector3(Vector3 vector)
{
return new Coordinates(vector.x, vector.y, vector.z);
}
internal static Vector3 ToVector3(Coordinates c)
{
return new Vector3(c.X, c.Y, c.Z);
}
These are in the Coordinates class, which has [ProtoContract] and [ProtoMember] for X, Y and Z. Commenting these 2 methods out stops me from receiving exceptions but the serialization still doesn't work (the User properties are all "new")
SOLVED
After giving up all hope on protobuf-net I switched over to DataCotractSerializer which somehow worked on Unity. I still got many issues so I decided to turn off the encryption and read the XML using Visual Studio; the file was perfectly ok. I still had a lot of issues with my 3 event handlers (2 were hooked up on game start, the other each time a special object is created), so I had to remove the event handlers and do the operations manually (what a pain in the a$$).
After all of this, I managed to add Protobuf-net back and everything work as it should (note that protobuf-net gives me a 89 bytes file agains DCS' 3.5 KB file)
So, the final solution to this extremely weird issue was:
Disable a fully functional RijndaelManaged implementation
Disable all event handlers
If someone can help me understand why RijdnaelManaged did work on Visual Studio but not Unity, please leave a comment.
I am building a game with XNA, and I have a custom file format for my game's levels. I want to load them and parse them myself, without using XNA's content pipeline. I have this much working, and by adding the files to the Content project I can even edit them in Visual Studio (which I also want).
The Problem: I get a warning stating "Project item 'item.lvl' was not built with the XNA Framework Content Pipeline. Set its Build Action property to Compile to build it."
I do not want XNA to Compile it, since I am doing my own parsing. How can I disable the warning?
Set the file's Build Action to None, and then set it to Copy if newer. That will cause the file to be written to the proper output directory without putting it through the Content Pipeline.
The solution could be create a custom content importer as explained here: Creating a Custom Importer and Processor. To create a simple content importer you have to inherit your class from the ContentImporter<T> (abstract class) and override the Import() method.
Here is a simple example from the msdn:
//...
using Microsoft.Xna.Framework.Content.Pipeline;
class PSSourceCode
{
const string techniqueCode = "{ pass p0 { PixelShader = compile ps_2_0 main(); } }";
public PSSourceCode(string sourceCode, string techniqueName)
{
this.sourceCode = sourceCode + "\ntechnique " + techniqueName + techniqueCode;
}
private string sourceCode;
public string SourceCode { get { return sourceCode; } }
}
[ContentImporter(".psh", DefaultProcessor = "PSProcessor", DisplayName = "Pixel Shader Importer")]
class PSImporter : ContentImporter<PSSourceCode>
{
public override PSSourceCode Import(string filename,
ContentImporterContext context)
{
string sourceCode = System.IO.File.ReadAllText(filename);
return new PSSourceCode(sourceCode, System.IO.Path.GetFileNameWithoutExtension(filename));
}
}
I have a C# Web Service that is serializing my simple class:
[Serializable]
[XmlInclude(typeof(Bitmap))]
[XmlTypeAttribute(Namespace = "http://tempuri.org/")]
public class Class1
{
private static Bitmap _myImage = new Bitmap(#"C:\WebApplication1\ClassLibrary1\Untitled.png");
public Bitmap MyImage
{
get { return _myImage; }
set
{
_myImage = value;
}
}
}
Here's the asmx.cs code that does the serialization:
[WebMethod]
public string HelloWorld()
{
var c = new Class1();
XmlSerializer serializer = new XmlSerializer(typeof(Class1));
return XMLSerializer(c);
}
public string XMLSerializer(object pObject)
{
try
{
XmlSerializer xs = new XmlSerializer(pObject.GetType());
using (StringWriter stream = new StringWriter())
{
xs.Serialize(stream, pObject);
stream.Flush();
return stream.ToString();
}
}
catch (Exception ex)
{
return ex.ToString();
}
}
Looks prety straight forward. However, the XML generated by the XmlSerializer is producing and error when I try to DeSerialize it.
{"There is an error in XML document (5, 5)."}
{"Parameter is not valid."}
When I try to load the generated XML into IE I get this error.
Switch from current encoding to specified encoding not supported. Error processing resource 'file:///C:/Users/mhall15/Deskt...
<?xml version="1.0" encoding="utf-16"?>
Here's the generated XML:
<?xml version="1.0" encoding="utf-16"?>
<Class1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<MyImage xmlns="http://tempuri.org/">
<Palette />
</MyImage>
</Class1>
Any ideas what's going on?
During the serialization, replace "encoding="utf-16" with "encoding="utf-8"" and that will cut it. The source of the problem - I'm not sure, but I've ran into it numerous times, and that's how I dealt with it.
That's how to deal with the IE issue.
The deserialization should be amongst these lines. I'm posting the kind of arbitrary code I normally use:
public static object DeserializeFromXML<T>(string _input)
{
object _temp = Activator.CreateInstance<T>();
Type expected_type = _temp.GetType();
_temp = null;
XmlSerializer serializer = new XmlSerializer(expected_type);
StringReader stringWriter = new StringReader(_input);
object _copy = serializer.Deserialize(stringWriter);
return _copy;
}
In the above example, I'm using templating for reusability sake. You should be able to call the method by saying DeserializeFromXML < Class1 >(_xml_input) where xml input is the string. That will force the compiler to use the definition of the given class to deserialize the XML input. That way you wouldn't even have to change the encoding in the serialization. If it's also a case where you may or may not know the data type to deserialize with, you can use a strategy design pattern where you register the root type of the XML with it's associated generic type. Later on you can reference that registry and arbitrarily deserialize any XML input as long as the root type is registered. It's a trick i normally use as well. If more is needed on this, let me know, and I'll explain in detail.
In addition,if you are running IE 9, the new update to IE 9 makes it difficult to view XML. Press F12 - go to developer tools and change your browser mode to run as IE 8 instead of IE 9.
The project I'm currently working on uses Enterprise Libraries V3.1 framework for logging.
I need to take the log file that's generated and archive it off at specific points. The built in Trace Listeners seem to keep the file open in-between logging events. I've set up a custom Trace Listener which will append to a file and close it, so that the file is always shiftable.
It looks like this (minus error handling for clarity):
[ConfigurationElementType(typeof(CustomTraceListenerData))]
public class AlwaysClosedTextFileTraceListener : CustomTraceListener
{
private string logFilePath;
public AlwaysClosedTextFileTraceListener ()
{
logFilePath = #"hardcodedpath\log.txt";
}
public override void Write(string message)
{
using (StreamWriter logFile = File.AppendText(logFilePath))
{
logFile.Write(message);
logFile.Flush();
logFile.Close();
}
}
public override void WriteLine(string message)
{
using (StreamWriter logFile = File.AppendText(logFilePath))
{
logFile.WriteLine(message);
logFile.Flush();
}
}
public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
{
if (data is LogEntry && this.Formatter != null)
{
WriteLine(this.Formatter.Format(data as LogEntry));
}
else
{
WriteLine(data.ToString());
}
}
}
This works fine, but I'd much rather be passing in the path as a parameter somehow, rather than hardcoding it.
For fun, I tried adding it to the constructor, to see what happens:
public LogFolderTraceListener(string logFilePath)
{
this.logFilePath = logFilePath;
}
When I do this, I get returned an error message hinting towards what I'm doing wrong:
System.InvalidOperationException : The type 'AlwaysClosedTextFileTraceListener' specified for custom trace listener named 'MyLogFile' does not a default constructor, which is required when no InitData is specified in the configuration.
From here on in, my investigations have very much come to, the opposite of dead ends, infinite probability problems.
I have found this thumbing through the source code for the inbuilt RollingTraceListener
There is a class RollingFlatFileTraceListenerData : TraceListenerData which seems to contain all the settings passed into the constructor
Camped out at the bottom of the file for RollingFlatFileTraceListenerData is the class RollingTraceListenerAssembler : TraceListenerAsssembler which seems to be a factory
There is another class SystemDiagnosticsTraceListenerNode : TraceListenerNode which seems to make the Data class presentable to the configuration application
My question is this: how do I create a CustomTraceListener with a configurable parameter of path?
The CustomTraceListener derives from TraceListener, this has a StringDictionary called Attributes.
This will contain all the attributes in the configuration line for your TraceListener and can be gotten out by name, eg.
string logFileName= Attributes["fileName"]
I suspect that perhaps the Enterprise Application Blocks although (probably) wonderful, seem unnecessarily complicated and ultimately more trouble than their worth for this kind of customisation.
the problem is typical microsoft .. (add your own adjectives here) ..
1) when you add a custom trace listener, the 'raw' app.config statement added is:
name="Custom Trace Listener" initializeData="" formatter="Text Formatter" />
2) notice the 'initializeData' - this is what the cryptic error message is calling'InitData'.
3) So what its all saying is that you need to have a constructor that accepts initialization data - in vb parlance:
sub new (byval initstuff as string)
4) OR remove the 'initializeData=""' and have a default constructor:
sub new()
I suspect the P&P folks live in a bubble.
riix.
For what it is worth this is how I implemented it. In my this.buildCurrPath() I can read from a config file or in this case I just get the "launch pad" for the web app. But it works fine for me. I have not put it into any production code yet, but it should go out soon.
[ConfigurationElementType(typeof(CustomTraceListenerData))]
public class CustomListener: CustomTraceListener
{
#region Fields (3)
private int logSize;
StreamWriter sw;
#endregion Fields
#region Constructors (1)
public CustomListener ():base()
{
string startPath = this.buildCurrPath();
sw = new StreamWriter(startPath + "\\Logs\\test.log");
sw.AutoFlush = true;
}
I have just had the same issue (except with Enterprise Library v4.1).
The solution I've found is to remove the default constructor and the only have a constructor with a string parameter for the filename i.e.
public AlwaysClosedTextFileTraceListener (string pathParameter)
{
logFilePath = pathParameter;
}
Then in the app.config put your path in the initializeData parameter
<add ... initializeData="C:\Logs\myLog.log" />
Whilst this isn't recognised by the Entriprise Library configuration editor and isn't as neat as it could be, it works as long as there is only one parameter.
If someone works out how to do it properly, please post and let us know - it's not supposed to be this difficult, surely.