I'm currently testing in visual studio 2010. I made a client and server which both will connect through UdpClient.
I want to send an object from the client to the server. I have two methods to convert the object to bytes and to convert it to an object. Now, when I test my application I can't convert it back to an object once received on the server
My server sees that the object is received and tries to convert it from bytes to the object but this gives an error.
System.Runtime.Serialization.SerializationException was unhandled Message=Unable to find assembly
This seems okay because both applications are in a different namespace...
These are my methods to convert; Both the same on client and server
public byte[] ToBytes() {
using (MemoryStream stream = new MemoryStream()) {
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, this);
stream.Position = 0;
byte[] byteRij = new byte[1024];
stream.Read(byteRij, 0, (int)stream.Length);
return byteRij;
}
}
public static Datagram ToDatagram(byte[] rij) {
using (MemoryStream stream = new MemoryStream()) {
stream.Write(rij, 0, rij.Length);
stream.Position = 0;
BinaryFormatter formatter = new BinaryFormatter();
return (Datagram)formatter.Deserialize(stream);
}
}
How can I resolve this?
Thanks in advance
You need to put all classes that are serialized in a class library project. Use that library in both the server and the client.
Also note that UDP is not reliable. There is no guarantee that your messages arrive at all.
BinaryFormatter is deeply tied to the type metadata. It is not a good choice here, since you have different types. Actually IMO it isn't a good choice anyway :) It is not very version tolerant, and is not portable.
I will openly recommend protobuf-net here (disclosure: I wrote it). It is free OSS, but uses google's protobuf format to fix all the BF problems. It is trivial to setup and use, is faster, and has smaller output than BinaryFormatter. Since it is contract-based you can have different types at each end, as log as they agree on the contract (matching field-numbers etc).
For example:
[ProtoContract]
public class Foo {
[ProtoMember(1)]
public string X {get;set;}
[ProtoMember(2)]
public int Y {get;set;}
}
And then just use ProtoBuf.Serializer.Serialize(stream, object) to write the data.
You can also work without attribute if you need, it takes a little more setup, but not much.
You may be experiencing problems with unsatisfied dependency. This may be caused by different namespaces or by trying to serialize external component, which isn't installed on server.
Say: you send object of type MyApp1.MyFoo.
Class MyFoo is also defined in your server, but as MyApp2.MyFoo (which is quite silly and means that you have to fix your design). Server doesn't know how to create an object of MyApp1.MyFoo because it isn't smart enough to find out that he also has this class defined, but named MyApp2.MyFoo.
You should use same namespaces. This is what they're for. Also, they make handling dependencies easier. And MyApp.Server talking to MyApp.Client looks nice ;).
I hope you get the point.
Related
I'm basically asking the same thing that was asked here, however, that question was asked 8 years ago and the answer is no longer applicable to UWP.
I have a audio stream with http://someurl.com/stream that streams in audio/ogg format. I would like to be able to play that from an UWP app.
I see the NAudio library recommended a lot (after all, it's used in the above example), however it's very larger and has fairly lackluster documentation and very few up-to-date examples (they used to have a streaming example, but from what I'm able to download off Codeplex, it was replaced with a regular local-file player example). I'm not experience enough to make sense of the little documentation and example code they do have.
I'm honestly not even sure where to begin. I've never handled a stream like this (or any stream). Maybe the NAudio library isn't the way to go?
Code would be appreciated, but even pointers to sources where I could read up on playing such stream would be very helpful as my google-fu has failed me.
Thank you.
EDIT:
private void PlayMedia() {
System.Uri manifestUri = new Uri("http://amssamples.streaming.mediaservices.windows.net/49b57c87-f5f3-48b3-ba22-c55cfdffa9cb/Sintel.ism/manifest(format=m3u8-aapl)");
var mediaPlayer = new Windows.Media.Playback.MediaPlayer();
~~~~~~~~~~~~ -> "'Media Player' does not contain a constructor that takes 0 arguments."
mediaPlayer.Source = MediaSource.CreateFromUri(manifestUri);
mediaPlayer.Play();
}
but I can't get the MediaPlayer class to work. It says for example the x.Play() doesn't exist.
You have not posted your code segment. So I could not locate the problem of Visual Studio alerting "doesn't exist" accurately. If you want to use "MediaPlayer" class please add Windows.Media.Core and Windows.Media.Playback namespace at first. And you could reference the following code implementing a basic mediaplayer.
using Windows.Media.Core;
using Windows.Media.Playback;
......
private void PlayMedia()
{
System.Uri manifestUri = new Uri("http://amssamples.streaming.mediaservices.windows.net/49b57c87-f5f3-48b3-ba22-c55cfdffa9cb/Sintel.ism/manifest(format=m3u8-aapl)");
var mediaPlayer = new MediaPlayer();
mediaPlayer.Source = MediaSource.CreateFromUri(manifestUri);
mediaPlayer.Play();
}
The error message of Media Player does not contain a constructor that takes 0 arguments is means that there is no constructor with no arguments in the MediaPlayer class. Please try use the full name of constructor with namespace.
var mediaPlayer = new Windows.Media.Playback.MediaPlayer();
I am developing a tool, that encrypts emails with S/MIME in bulk within Outlook 2013. It works so far, but when I am trying to encrypt a REALLY BIG email (in the test case it was about 60MB raw). I get a COMException stating unsufficient ressources.
I can go around this, by working direktly with EWS and MimeKit (which works like a charm! Thank you #jstedfast), but I'd like to find a way to work in Outlook, for network traffic considerations. I know these changes will be synched to Exchange eventually, but during the process itself, it is independent of bandwidth.
I am also looking at MapiEx, but if there is an easier solution, than having yet another dependency (and with MFC too), I'd be happy! Maybe there are some settings, I'd have to make before.
A bit of code. The Exception it caught somewhere else.
public void String SetEncryption(MailItem mailItem)
{
PropertyAccessor pa = null;
try
{
pa = mailItem.PropertyAccessor;
Int32 prop = (int)pa.GetProperty(_PR_SECURITY_FLAGS);
Int32 newprop = prop | 1;
pa.SetProperty(_PR_SECURITY_FLAGS, newprop);
}
finally
{
Marshal.FinalReleaseComObject(pa);
pa = null;
}
}
Edit: The Exception is not coming, when the encryption is set, but when the result is saved, after the encryption is set.
SetEncryption(mailItem);
mailItem.Save();
I solved it myself.
Since I had the problems in Outlook itself, I was trying MAPIEx to access the raw S/MIME Attachment in the email and de-/encrypt it using MimeKit/BouncyCastle.
The same problem occoured, but with a different error message, which lead me to the following site: ASN.1 value too large.
To sum it up: The Crypto API has two signatures. One which takes a byte array and one, which takes a stream. The first one has an arbitrary imposed (!!!) limit of 100 Million Bytes. Since the enveloped CMS has double base64 the ratio of this 100 MB is 9/16, which is round about 56 MB.
I assume, that Outlook uses the same API-Call and therefore has this limit.
I know it is not a fact, but the evidence strongly supports this theory. :)
Check if KB 2480994 is installed: http://support.microsoft.com/kb/2480994
I have 2 specific questions with regards to passing a System.IO.Stream (from a method) and deserialization into object (another method).
XML Response I get from a WebRequest (please note there are no root tags)
<?xml version="1.0" encoding="UTF-8"?>
<response id="-2d953936:14174bb0cf3:-5213">
<date>2013-10-01 12:01:55.532999</date>
<status>
<current>open</current>
<next>after</next>
<change_at>16:00:00</change_at>
</status>
<message>Market is open</message>
<unixtime>1380643315</unixtime>
</response>
Method 1 - ResponseMethod - Currently returning string
private static string GetResponse(HttpWebRequest request)
{
var v_Response = request.GetResponse();
var v_DataStream = v_Response.GetResponseStream();
var v_Reader = new System.IO.StreamReader(v_DataStream);
var x_XMLResponse = v_Reader.ReadToEnd();
//Close all Stream logic
v_Reader.Close(); v_DataStream.Close(); v_Response.Close();
return x_XMLResponse;
}
Method 2 - Convert the XML to an object
// I would use XDocument and Lin2XML to get my typed object - for example MarketStatus
Questions are:
I am currently passing string from Method 1. That doesnt help me in deserializing from XML to object. Should I be passing the return value as StreamReader and then use that as an input into method 2 to get my typed object. Is that a standard approach or there are better ways to this?
My ultimate objective is that the return value from second method should be an object.
Additional Note:
The reason this functionality is broken into 2 methods because I want the web response method and deserailization separate for testing purposes.
I don't have an XSD but have created a MarketStatus Class
Any code snippets/suggestions will really appreciate
We typically use a generic method, similar to the following (simplified for posting), which uses the XMLSerializer to deserialize an XML string representation into the corresponding object.
public T ReturnObjectfromXml<T>(string xmlForm)
{
XmlSerializer xs = new XmlSerializer(typeof(T));
StringReader sr = new StringReader(xmlForm);
XmlTextReader xts = new XmlTextReader(sr);
return ((T)xs.Deserialize(xts));
}
Hope this helps.
Regards,
It looks like you are doing some type of message passing. You will be better off using WCF or ASP.NET Web API instead of rolling your own infrastructure code (to serialize and de-serialize).
To answer question 1: No, it is better to return a string and dispose of the reader as soon as you are done with it. See When should I dispose my objects in .NET?
Comment on note 1: In most cases, you wouldn't want to unit test the serialization/deserialization.
My question is related with the C# implementation of the google protocol buffers (protobuf-csharp-port, by jon skeet, great job!)
I am experiencing troubles with the extensions: let's say I wrote:
"transport_file.proto" with a "transport message" and some code to
deal with it "code_old".
and I wrote an extension of the transport message on
"Mytransport.proto" file, and new code to read it "code_new".
I'm trying to read a new message (from MyTransport.proto) with the code_old expecting to ignore the extension, but I get an exception in the merge method from TextFormat: "transport" has no field named "whatever_new_field"
Transport.Builder myAppConfigB = new Transport.Builder();
System.IO.StreamReader fich = System.IO.File.OpenText("protocolBus.App.cfg");
TextFormat.Merge(fich.ReadToEnd(),myAppConfigB);
fich.Close();
new extended file looks like:
...
Transport
{
TransportName: "K6Server_0"
DllImport: "protocolBus.Transports.CentralServer"
TransportClass: "K6Server"
K6ServerParams
{
K6Server { host: "85.51.11.23" port: 40069 }
Service: "TZinTalk"
...
}
}
...
while the old one, not extended:
...
Transport
{
TransportName: "K6Server_0"
DllImport: "Default"
TransportClass: "Multicast"
}
...
The whole idea is to use the text based protocol buffer as a config file in which I write some params, and based on one of those I load and assembly (which will read the whole message with the new extension (params to initialize the object).
Any idea? (it is a desperate question :D )
I'm using MSVC# 2008Express edition, protobuf-csharp-port version 0.9.1 (someday I'll upgrade everything).
THANKS in advance.
I'm working on a non centrilized Publish-Subscribe framework of messages (for any written message in a proto file I auto create a Publish and a Subscriber class) with different transports. By the default I use multicast, but broadcast and a "UDP star" are also included. I let the extension mechanism to let people add new transports with its owm config params that should be read by my main code_old (just to load the assembly) and let the new transport (.dll) read it again (fully).
Curious? the previous, almost functional, version is in http://protocolbus.casessite.org
Update 1
Extended types in text format are enclosed in brackets (good to know, I was not aware of it :D ) so I should have written:
[K6ServerParams]
{
K6Server { host: "85.51.11.23" port: 40069 }
Service: "TZinTalk"
...
}
Protocol buffers are designed to be backwards and forwards compatible when using their binary format, but certainly the current code doesn't expect to parse the text format with unknown fields. It could potentially be changed to do that, but I'd want to check with the Java code to try to retain parity with that.
Is there any reason you're not using the binary representation to start with? That's the normal intended usage, and the one where the vast majority of the work has gone in. (Having said which, it all seems a bit of a blur after this long away from the code...)
I am trying to use memcached with both a php (memcached) and C# (enyim) client.
I have a scenario where I want to CAS a value in php. To do this I am using the following code:
$memcached = new Memcached;
$memcached->addServer('localhost', 11211) or die ("Could not connect");
$memcached->setOption(Memcached::OPT_COMPRESSION, false); // the enyim client doesn't support compression
do {
$entries = $memcached->get($theKey, null, $cas);
if ($memcached->getResultCode() == Memcached::RES_NOTFOUND) {
$entry = somearray("foo");
$memcached->add($theKey, $entry);
} else {
$entries[] = "bar";
$memcached->cas($cas, $theKey, $entries);
}
}
while ($memcached->getResultCode() != Memcached::RES_SUCCESS AND $memcached->getResultCode() != Memcached::RES_END);
This works all well and fine to begin with.
But then, when the C# client CAS's the same value it goes wrong.
Php gives a warning at:
$entries = $memcached->get($theKey, null, $cas);
namely that:
PHP Warning: Memcached::get(): could not uncompress value in ... at line ...
And as a result an infinite loop occurs.
Now I tried to get the key from the memcached server via telnet and the data was right there.
In php I am also able to SET to this key without a problem.
I noticed one thing: after the php client has SET something, the flag was 0.
Now after the C# client has CAS'd the value, the flag was 274.
Is there some flag collision on the php lib going on? Or is it something else?
If anyone can help me resolve this problem I'd be gratefull!
lordstyx
[EDIT]
Well then. Since this question isn't getting an answer let me put it differently.
Is there a way to stop the C# client from setting flag 274?
So I eventually found an answer to my problem. It might not help all of you, because I switched from the Enyim to the BeIT memcached client (http://code.google.com/p/beitmemcached/)
Now to make the BeIT client compatible with the php client you have to change Serializer.cs
In the enum SerializedType I changed the number of "String" to 0 and ByteArray to 2, which gave this:
internal enum SerializedType : ushort
{
ByteArray = 2,
Object = 1,
String = 0, //mod: turned around the numbers for String and ByteArray so it is compatible with php client
Datetime = 3,
....
I believe I went with BeIT because I couldn't find or figure out how the flags worked in the Enyim client. If you understand how it work though, I'm sure that you can change that client in a same manner
If I am not wrong, mixing languages/platforms with memcached is a bad idea. See another question on similar topic.
For the record. Since the library is open source, then its possible to modify.
In the class Enyim.Caching.Memcached.DefaultTranscoder, change the function
public static uint TypeCodeToFlag(TypeCode code)
{
return (uint)((int)code | 0x0100);
}
to
public static uint TypeCodeToFlag(TypeCode code)
{
if (code == TypeCode.String)
{
return 0;
}
return (uint)((int)code | 0x0100);
}
274 = TypeCode.String | 0x0100
Since i don't know the memcache protocol then i don't know whats doing. However, php's memcache requires 0, so i set to zero when the variable defined is a string.
ps: beitmemcached hasn't be updated for a long while.