Is it possible to serialize a CouchbaseClient to write it to a Memory Mapped file?
When I try do this:
[Serializable]
public class DocumentDatabaseConnection
{
public CouchbaseClient DocumentStoreConnection { get; set; }
}
static void main(string [] args)
{
CouchbaseClientConfiguration config = new CouchbaseClientConfiguration();
config.Urls.Add(new Uri("http://localhost:8091" + "/pools/"));
config.Bucket = "myBucket";
config.BucketPassword = "123456";
DocumentDatabaseConnection clientConnection = new DocumentDatabaseConnection();
clientConnection.DocumentStoreConnection = new CouchbaseClient(config);
try
{
//Here is where I try to convert it to a byte array to save in MMF
var myMMFObject = ObjectToByteArray(clientConnection);
WriteObjectToMMF("C:\\TEMP\\TEST.MMF", myMMFObject);
string myMMF = ReadObjectFromMMF("C:\\TEMP\\TEST.MMF").ToString();
}
catch(Exception e)
{
throw;
}
}
I get a SerializationException, for the Couchbase.CouchbaseClient. If it is possible to serialize how would that be done. Couchbase.CouchbaseClient was installed via NuGet.
How would one share a Couchbase.CouchbaseClient accross threads?
The official documentation specifically covers how to instantiate and share a single client instance. I would follow that for best practices, you can find the link here http://docs.couchbase.com/couchbase-sdk-net-1.3/#instantiating-the-client
Also there is some more detail regarding the client for C# located here: http://docs.couchbase.com/couchbase-sdk-net-1.2/#encapsulating-data-access
Related
I'm trying to send a class with some variables trough named pipes, and it keeps giving me this error when I try to deserialize the data I received.
This is the serialization/deserialization code:
// Serialize into bytes
private byte[] SerializeToBytes<T>(T source)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(stream, source);
return stream.ToArray();
}
}
// Deserialize from bytes (BinaryFormatter)
private T DeserializeFromBytes<T>(byte[] source)
{
using (var stream = new MemoryStream(source))
{
var formatter = new BinaryFormatter();
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
Both projects use this same code, I have a server project and a client project that can send and receive data, it was working fine with sending and receiving strings but in the end i need it to send and receive custom data like a class.
this is how I send / recieve data:
// Sending Data
private void _SendBttn_Click(object sender, EventArgs e)
{
AchievementInfo info = new AchievementInfo("1337", true);
server.WriteBytes(SerializeToBytes(info));
}
// Receiving Data
private void _ServerWorker_DoWork(object sender, DoWorkEventArgs e)
{
server = new ServerPipe("testerSV", p => p.StartByteReaderAsync());
server.DataReceived += (sndr, args) => this.BeginInvoke((Action)(() =>
_RecievedData.Text =
DeserializeFromBytes<AchievementInfo>(args.Data).ToString()));
}
Both projects also have the class AchievementInfo this is what it looks like:
[Serializable]
public class AchievementInfo
{
public string ID { get; }
public bool UnlockState { get; set; }
public bool CurrentUnlockState { get; }
public AchievementInfo() {}
public AchievementInfo(string id, bool currentState)
{
ID = id;
CurrentUnlockState = currentState;
UnlockState = currentState;
}
}
I've search for other posts with a similar problem but none of the solutions worked so far. I currently have no idea what's causing this, but I know it's something to do with it being 2 different projects, since serializing and deserializing in the same project works just fine.
Edit: Projects are named NamedPipes and PipesClient
The problem is your use of two separate AchievementInfo classes, one in each project. What's happening is that the full namespace (or something calculated from it) of the class is encoded into the serialised data. When it is deserialised via a separate project it can't find the class because it's looking for the one in the namespace of the project that serialised it.
The correct way to do this is to define a DTO class in a shared library, and serialise and deserialise that. Often the DTO class would be a totally separate class than the classes at either end, and you'd convert the DTO appropriately at each end before/after serialising.
However for your case, you could try the quick and dirty solution of just using the AchievementInfo class for the DTO. Just make sure it's in a shared class library so the namespace is the same at both ends.
Do note that BinaryFormatter is considered insecure, and Microsoft warn against using it.
This question already has answers here:
What is App.config in C#.NET? How to use it?
(7 answers)
Closed 3 years ago.
So I want to execute my program with an .exe, and I would like to configure my program without actually write into the code.
I have some yes-no questions in my code, like:
What would you like to zip? File/Directory.
Edit: I don't want to answer these questions in the console application, I would like to answer these before, like before "settings".
And my question is, can I answer these questions without writing into the code, and make this app executable in this way? Are there any programs for it?
Thanks for the answers!
You have 2 approaches you can use depending on your usage preference, the first suggestion is in case you are using your program and you don't set the values too often
You can use app.config file and add relevant values and call them via your code as variables.
You can write to a xml file or json file a small configuration file abd edit it easily and it is also good for clients using your app to change configuration easily via configuration file.
To do this try use xml serialisation and deserialisation object,
I'll add code sample if required.
Edit
to use external configuration you need the next classes:
1. Configuration data object
[Serializable]
public class Configuration : ICloneable
{
public Configuration()
{
a = "a";
b= "b"
}
public string a { get; set; }
public string b { get; set; }
public object Clone()
{
return new Configuration
{
a = a,
b= b
};
}
}
File write and read class
public class ConfigurationHandler
{
// full path should end with ../file.xml
public string DefaultPath = "yourPath";
public ConfigurationHandler(string path = "")
{
if (!File.Exists(DefaultPath))
{
Directory.CreateDirectory(Path.GetDirectoryName(DefaultPath));
FileStream file = File.Create(DefaultPath);
file.Close();
Configuration = new Configuration();
SaveConfigurations(DefaultPath);
}
}
public void SaveConfigurations(string configPath = "")
{
if (string.IsNullOrEmpty(configPath))
configPath = DefaultPath;
var serializer = new XmlSerializer(typeof(Configuration));
using (TextWriter writer = new StreamWriter(configPath))
{
serializer.Serialize(writer, Configuration);
}
}
public Configuration LoadConfigurations(string configPath = "")
{
if (string.IsNullOrEmpty(configPath))
configPath = DefaultPath;
using (Stream reader = new FileStream(configPath, FileMode.Open))
{
// Call the Deserialize method to restore the object's state.
XmlSerializer serializer = new XmlSerializer(typeof(Configuration));
Configuration = (Configuration)serializer.Deserialize(reader);
}
return Configuration;
}
}
to get the configuration instance you can use it from your program:
static void Main(string[] args)
{
var config = new ConfigurationHandler().LoadConfigurations();
//....
}
I am trying to find a way/helper to convert.Net Class to Avro.Generic.GenericRecord . Currently, I am manually adding field-name and field-value to Generic record. Is there a serializer/converter which I can use to convert the object to generic record and publish on to a kafka topic.
class Plant
{
public long Id { get; set; }
public string Name { get; set; }
public List<PlantProperties> PlantProperties{ get; set; }
}
class PlantProperties
{
public long Leaves{ get; set; }
public string Color{ get; set; }
}
Please suggest.
Assuming you are using the Confluent Schema Regsitry, you can use their .NET client1
https://github.com/confluentinc/confluent-kafka-dotnet
Copied from the examples folder
using (var serdeProvider = new AvroSerdeProvider(avroConfig))
using (var producer = new Producer<string, GenericRecord>(producerConfig, serdeProvider.GetSerializerGenerator<string>(), serdeProvider.GetSerializerGenerator<GenericRecord>()))
{
Console.WriteLine($"{producer.Name} producing on {topicName}. Enter user names, q to exit.");
int i = 0;
string text;
while ((text = Console.ReadLine()) != "q")
{
var record = new GenericRecord(s);
record.Add("name", text);
record.Add("favorite_number", i++);
record.Add("favorite_color", "blue");
producer
.ProduceAsync(topicName, new Message<string, GenericRecord> { Key = text, Value = record })
.ContinueWith(task => task.IsFaulted
? $"error producing message: {task.Exception.Message}"
: $"produced to: {task.Result.TopicPartitionOffset}");
}
}
cts.Cancel();
}
Where, in your case, update the record.Add uses accordingly
However, since you have a class, therefore, you should try to use SpecificRecord, rather than serializing back and forth between Avro and a .NET class via a GenericRecord. See the README section on the AvroGen tool for examples of this
1. I'm not aware of an alternative .NET library
Below are the steps I did to solve the problem using the suggestion from #cricket_007.
To avoid the complexity of writing the avro schema, create the c# classes first then use AvroSerializer to generate schema.
AvroSerializer.Create().WriterSchema.ToString()
This will generate the schema json for the class.
Move it to a schema file and
Make all the types to have nulls as Required
Then used avro_gen.exe tool to regenerate class files which implements ISpecific Record.
Add used the below code to publish to queue
using (var serdeProvider = new AvroSerdeProvider(avroConfig))
using (var producer = new Producer<string, MYClass>(producerConfig,
serdeProvider.GetSerializerGenerator<string>(),
serdeProvider.GetSerializerGenerator<MYClass>()))
{
Console.WriteLine($"{producer.Name} producing on
{_appSettings.PullListKafka.Topic}.");
producer.ProduceAsync(_appSettings.PullListKafka.Topic, new
Message<string, MYClass> { Key = Guid.NewGuid().ToString(), Value = MYClassObject})
.ContinueWith(task => task.IsFaulted
? $"error producing message: {task.Exception.Message}"
: $"produced to: {task.Result.TopicPartitionOffset}");
}
some links to help do this.
https://shanidgafur.github.io/blog/apache-avro-on-dotnet
https://github.com/SidShetye/HelloAvro/tree/master/Avro
I have got a server/client relationship where the client pulls an ArrayList from the server. If I set the server to always send an empty ArrayList then I don't get this error. So clearly the problem is that my data is too big for the connection and that it's closing before all the data can get through.
I have looked into this issue and I have added the features suggested by this question/answer:
https://stackoverflow.com/a/285542/3036134 Many solutions suggest the same thing.
I believe that I have implemented something incorrectly (I think it's most likely the Service Behaviour MaxItemsInObjectGraph as I am still getting the same error. I unfortunately can't figure out what's wrong with it though. Here's my code:
The error I'm receiving:
CommunicationException was unhandled. The underlying connection was closed: The connection was closed unexpectedly.
My WCF Service Code:
[ServiceContract]
public interface IModelData
{
[OperationContract]
ArrayList GetData();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, MaxItemsInObjectGraph = 2147483647)]
public class ModelDataClient
{
ChannelFactory<IModelData> HttpFactory;
IModelData HttpProxy;
public ModelDataClient()
{
HttpFactory = new ChannelFactory<IModelData>(
new BasicHttpBinding(),
new EndpointAddress("http://localhost:8000/ModelData"));
HttpProxy = HttpFactory.CreateChannel();
}
public ArrayList GetData()
{
return HttpProxy.GetData();
}
}
[ServiceBehavior(UseSynchronizationContext = false, InstanceContextMode = InstanceContextMode.Single, MaxItemsInObjectGraph = 2147483647)]
public class ModelDataServer : IModelData
{
public delegate ArrayList GetData();
public GetData _GetData { get; set; }
public ModelDataServer()
{
}
public ArrayList GetData()
{
return _GetData();
}
}
My Client Side Code:
public partial class MainForm : Form
{
private ModelDataClient Client;
public MainForm()
{
InitializeComponent();
Client = new ModelDataClient();
}
private void Refresh()
{
ArrayList dataList = Client.GetData();
// ********** ERROR POINTS TO LINE ABOVE!!!!!!!!!!!!!!!!!!!!
// do something with datalist
}
}
My Server Side Code:
public partial class ScraperForm : Form
{
ServiceHost Host;
ModelDataServer DataServer;
ArrayList Data;
public ScraperForm()
{
InitializeComponent();
#region Start Data Server
DataServer = new ModelDataServer();
DataServer._GetData = new ModelDataServer.GetData(this.GetData);
BasicHttpBinding bhttpb = new BasicHttpBinding();
bhttpb.MaxBufferSize = 2147483647;
bhttpb.MaxReceivedMessageSize = 2147483647;
bhttpb.ReaderQuotas.MaxDepth = 32;
bhttpb.ReaderQuotas.MaxStringContentLength = 8388608;
bhttpb.ReaderQuotas.MaxArrayLength = 16384;
bhttpb.ReaderQuotas.MaxBytesPerRead = 4096;
bhttpb.ReaderQuotas.MaxNameTableCharCount = 16384;
Host = new ServiceHost(DataServer, new Uri[]
{
new Uri("http://localhost:8000")
});
Host.AddServiceEndpoint(typeof(IModelData),
bhttpb,
"ModelData");
Host.Open();
Data = new ArrayList();
}
private void CloseSever()
{
Host.Close();
}
public void UpdateData() // Run on a timer
{
ArrayList Data = new ArrayList()
// Update Data
}
public ArrayList GetData() // This is called by server which is called by client
{
return Data; // no error if I return new ArrayList();
}
}
EDIT: Would the problem be being caused by not having DataContract/DataMembers?
UPDATE
I have rebuilt my new implementation from the ground up using this tutorial (and the related ones): http://blogs.msdn.com/b/brunoterkaly/archive/2013/10/28/wcf-programming-how-to-write-a-client-app-that-connects-to-a-wcf-service.aspx (For anyone interested).
Instead of using an ArrayList (lots of unboxing) and a Typed List (comes out as an array if used with WCF), I have instead opted to pass my data using a string with the following format:
"~" to denote the start of a new member of the list
"," to denote the end of one of the datatypes in my custom one.
So it might look like "~NAME,1.29,1,4,123.1~NAME,1.23,3,1,13.2" etc. I would suggest people who want to use lists use this instead.
I have run into a new problem with my new implementation, likely the same/similar problem. Please see my new question: Object reference not set to an instance of an object - WCF Service and Delegates (WCF Hosted before Delegate is instantiated)
Thanks for your help everyone.
What is your client-side configured as? You've displayed your server-side configuration, but don't forget that the client-side has it's own configuration settings.
Looking at your server-side configuration, it appears that the violation is occurring on the reception of the data on the client.
See here for an example. You can also do this programmatically as well.
Edit
Now I see in the comments that this ArrayList you are getting from the server contains your own user-defined type RFData. I believe now that this is likely the source of your problem.
Data Contracts describe the data that is being exchanged. Data Contracts are used between the Client and Server to serialize and de-serialize data that is being sent over the wire. You need to use Data Contracts/ Data Members when you are defining your own type to be used within the WCF model. Primitives as well as many of the built-in .NET types already have Data Contracts.
For your RFData type it would be something like this:
// Apply the DataContract to the type
[DataContract]
public class RFData
{
// Apply the DataMemberAttribute to the various properties
[DataMember]
public double RFDouble { get; set; }
[DataMember]
public int RFInt { get; set; }
[DataMember]
public string RFString { get; set; }
}
I know you have several integers and doubles, but you get the gist. Here is a really helpful guide on Data Contracts from MSDN.
I am trying to use ServiceStack to return a file to a ServiceStack client in a RESTful manner.
I have read other questions on SO (here and here) which advise using HttpResult and a FileInfo object or MemoryStream to allow the ContentType header to be changed to the relevant file type.
This works for me when I call the service via a browser, the correct file automatically starts to download. How do I consume the file using one of the ServiceStack clients though?
I'm using a Request DTO and trying to return using something similar to
return new HttpResult(new FileInfo("file.xml"), asAttachment:true) {
ContentType = "text/xml"
};
How would I consume this with the JsonServiceClient for example?
I had a similar requirement which also required me to track progress of the streaming file download. I did it roughly like this:
server-side:
service:
public object Get(FooRequest request)
{
var stream = ...//some Stream
return new StreamedResult(stream);
}
StreamedResult class:
public class StreamedResult : IHasOptions, IStreamWriter
{
public IDictionary<string, string> Options { get; private set; }
Stream _responseStream;
public StreamedResult(Stream responseStream)
{
_responseStream = responseStream;
long length = -1;
try { length = _responseStream.Length; }
catch (NotSupportedException) { }
Options = new Dictionary<string, string>
{
{"Content-Type", "application/octet-stream"},
{ "X-Api-Length", length.ToString() }
};
}
public void WriteTo(Stream responseStream)
{
if (_responseStream == null)
return;
using (_responseStream)
{
_responseStream.WriteTo(responseStream);
responseStream.Flush();
}
}
}
client-side:
string path = Path.GetTempFileName();//in reality, wrap this in try... so as not to leave hanging tmp files
var response = client.Get<HttpWebResponse>("/foo/bar");
long length;
if (!long.TryParse(response.GetResponseHeader("X-Api-Length"), out length))
length = -1;
using (var fs = System.IO.File.OpenWrite(path))
fs.CopyFrom(response.GetResponseStream(), new CopyFromArguments(new ProgressChange((x, y) => { Console.WriteLine(">> {0} {1}".Fmt(x, y)); }), TimeSpan.FromMilliseconds(100), length));
The "CopyFrom" extension method was borrowed directly from the source code file "StreamHelper.cs" in this project here: Copy a Stream with Progress Reporting (Kudos to Henning Dieterichs)
And kudos to mythz and any contributor to ServiceStack. Great project!
You wouldn't consume files with the ServiceStack's .NET ServiceClients as they're mainly for sending DTO's.
You can just use any normal WebRequest to download files, in the v3.9.33 of ServiceStack introduced some handy WebRequest extensions HTTP Utils that make this easy, e.g:
For a text file:
var xmlFile = downloadUrl.GetXmlFromUrl(responseFilter: httpRes => {
var fileInfoHeaders = httpRes.Headers[HttpHeaders.ContentDisposition];
});
Where fileInfoHeaders contains the W3C ContentDisposition HTTP Header, e.g. when returning a FileInfo, ServiceStack returns:
attachment;filename="file.xml";size={bytesLen};
creation-date={date};modification-date={date};read-date={date};
To download a binary file you can use:
var rawBytes = downloadUrl.GetBytesFromUrl(httpRes => ...);
I have found mythz answer to work well, but it is also possible to use their built in JSonServiceClient to also process file requests as well, just in a slightly non-intuitive way because you can't actually use the return type you would expect.
For a model definition like this:
[Route("/filestorage/outgoing/{Name}.{Extension}", "GET")]
[Route("/filestorage/outgoing", "GET")]
public class GetFileStorageStream : IReturn<HttpResult>
{
public string Name { get; set; }
public string Extension { get; set; }
public bool ForDownload { get; set; }
}
You can define your service to return an HttpResult:
public class FileStorageService : Service
{
public HttpResult Get(GetFileStorageStream fileInformation)
{
var internalResult = GetFromFileStorage(fileInformation);
var fullFilePath = Path.Combine("C:\Temp", internalResult.FileName);
return new HttpResult(new FileInfo(fullFilePath), asAttachment: fileInformation.ForDownload);
}
}
Then on the client side you can use this Get template to properly get the web context:
var client = new JsonServiceClient("http://localhost:53842");
var httpResponse = client.Get<HttpWebResponse>("/filestorage/outgoing/test.jpg");
pictureBox1.Image = Image.FromStream(httpResponse.GetResponseStream());
I found it was not possible to use the new API Get methods as they would attempt to deserialize the HttpResult which isn't actually a true return type but a class representing the web context that service stack has created.
You can intercept the response prior to it being handled by using a response filter, like below:
ServiceClientBase.HttpWebResponseFilter = response =>
{
if (response.Headers["Content-Disposition"] != null)
{
var t = response.DownloadText();
Console.WriteLine(t);
}
};
However, this is not the best way to handle it, since the actual call to client.Method() will result in an ArgumentException when the client attempts to read the response stream (since it has been read previously by response.DownloadFile(...). I haven't yet figured out a way to handle it gracefully, but I 'll update my answer if I do.