Issue with .Net Remoting - c#

I am making an application in c#.I am using .Net Remoting for calling the method of windows application in web application.For communication between windows and web application i made one remoting object in which i declare one method.In windows application i have collection of one class and that class is declared in remote object.
Now my problem is that whenever i am calling the interface method,the collection value becomes zero.Before calling that method it contains some data.
Also whenever i am inserting hard coded value then its working but whenever i am inserting runtime value,its giving problem.I am using threading to insert the data into the collection.
Remote object has two components as StreamDataInfo.cs and IRemoteStreamData.cs as.These two are different classes in one class library.
namespace StreamDataService
{
public interface IRemoteStreamData
{
List<string> GetPatientHistory(string BedID);
}
}
namespace StreamDataService
{
[Serializable] public class StreamDataInfo:MarshalByRefObject
{
public string m_PortNumber { get; set; }
public string m_BedID { get; set; }
public List<string> m_StreamData { get; set; }
}
}
And in server application i wrote interface method as
public List<string> GetPatientHistory(string PortNumber)
{
StreamDataInfo objStreamDataInfo = new StreamDataInfo();
lock (this)
{
objStreamDataInfo = (from temp in listStreamDataInfo
where temp.m_PortNumber.Equals(PortNumber.ToString())
select temp).SingleOrDefault();
}
return objStreamDataInfo.m_StreamData;
}
Please help me.Thanks in advance.

Generic collections are not supported in remoting. You can either use arrays or try your own implementation (a VB sample is here).

Related

C# Web API Objects

I have a C# Web API project which has a Product class:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
}
and the following method to get a Product by it's Id:
public Product GetProduct(int id)
{
Product item = repository.Get(id);
if (item == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
return item;
}
Say I now have 10 different C# projects (i.e. not in the same solution, and a mixture of Windows Forms, Console, MVC etc) that all want to call this method and get a Product. I want to reduce the need for all 10 separate projects to have to have a class file for a Product object which is just duplicating the same structure, and also avoid using a class library DLL that is added to each project, is this possible somehow?
I know when I've previously used web services in .NET (these were the original services that created a WSDL file, and also WCF services), Visual Studio (I think) automatically created these classes behind the scenes based on the WSDL information which meant you could just consume a service and not have to worry about hand crafting each object yourself.
Is this possible to do in a Web API environment?

Managing multiple versions of object in JSON

I have a class in C#, that has a number of variables. Let's call it "QuestionItem".
I have a list of this object, which the user modifies, and then sends it via JSON serialization (with Newtonsoft JSON library) to the server.
To do so, I deserialize the objects that are already in the server, as a List<QuestionItem>, then add this new modified object to the list, and then serialize it back to the server.
In order to display this list of QuestionItems to the user, I deserialize the JSON as my object, and display it somewhere.
Now, the problem is - that I want to change this QuestionItem and add some variables to it.
But I can't send this NewQuestionItem to the server, because the items in the server are of type OldQuestionItem.
How do I merge these two types, or convert the old type to the new one, while the users with the old version will still be able to use the app?
You are using an Object Oriented Language, so you might aswell use inheritance if possible.
Assuming your old QuestionItem to be:
[JsonObject(MemberSerialization.OptOut)]
public class QuestionItem
{
[JsonConstructor]
public QuestionItem(int Id, int Variant)
{
this.Id = Id;
this.Variant = Variant;
}
public int Id { get; }
public int Variant { get; }
public string Name { get; set; }
}
you can extend it by creating a child class:
[JsonObject(MemberSerialization.OptOut)]
public class NewQuestionItem : QuestionItem
{
private DateTime _firstAccess;
[JsonConstructor]
public NewQuestionItem(int Id, int Variant, DateTime FirstAccess) : base(Id, Variant)
{
this.FirstAccess = FirstAccess;
}
public DateTime FirstAccess { get; }
}
Note that using anything different than the default constructor for a class requires you to use the [JsonConstructor] Attribute on this constructor and every argument of said constructor must be named exactly like the corresponding JSON properties. Otherwise you will get an exception, because there is no default constructor available.
Your WebAPI will now send serialized NewQuestionItems, which can be deserialized to QuestionItems. In fact: By default, JSON.NET as with most Json libraries, will deserialize it to any object if they have at least one property in common. Just make sure that any member of the object you want to serialize/desreialize can actually be serialized.
You can test the example above with the following three lines of code:
var newQuestionItem = new NewQuestionItem(1337, 42, DateTime.Now) {Name = "Hello World!"};
var jsonString = JsonConvert.SerializeObject(newQuestionItem);
var oldQuestionItem = JsonConvert.DeserializeObject<QuestionItem>(jsonString);
and simply looking at the property values of the oldQuestionItem in the debugger.
So, this is possible as long as your NewQuestionItem only adds properties to an object and does neither remove nor modify them.
If that is the case, then your objects are different and thus, requiring completely different objects with a different URI in your API, as long as you still need to maintain the old instance on the existing URI.
Which brings us to the general architecture:
The most clean and streamline approach to what you are trying to achieve is to properly version your API.
For the purpose of this link I am assuming an Asp.NET WebApi, since you are handling the JSON in C#/.NET. This allows different controller methods to be called upon different versions and thus, making structural changes the resources your API is providing depending on the time of the implementation. Other API will provide equal or at least similar features or they can be implemented manually.
Depending on the amount and size of the actual objects and potential complexity of the request- and resultsets it might also be worth looking into wrapping requests or responses with additional information. So instead of asking for an object of type T, you ask for an Object of type QueryResult<T> with it being defined along the lines of:
[JsonObject(MemberSerialization.OptOut)]
public class QueryResult<T>
{
[JsonConstructor]
public QueryResult(T Result, ResultState State,
Dictionary<string, string> AdditionalInformation)
{
this.Result = result;
this.State = state;
this.AdditionalInformation = AdditionalInformation;
}
public T Result { get; }
public ResultState State { get; }
public Dictionary<string, string> AdditionalInformation { get; }
}
public enum ResultState : byte
{
0 = Success,
1 = Obsolete,
2 = AuthenticationError,
4 = DatabaseError,
8 = ....
}
which will allow you to ship additional information, such as api version number, api version release, links to different API endpoints, error information without changing the object type, etc.
The alternative to using a wrapper with a custom header is to fully implement the HATEOAS constraint, which is also widely used. Both can, together with proper versioning, save you most of the trouble with API changes.
How about you wrapping your OldQuestionItem as a property of QuestionItem? For example:
public class NewQuestionItem
{
public OldQuestionItem OldItem { get; set; }
public string Property1 {get; set; }
public string Property2 {get; set; }
...
}
This way you can maintain the previous version of the item, yet define new information to be returned.
Koda
You can use something like
public class OldQuestionItem
{
public DateTime UploadTimeStamp {get; set;} //if less then DateTime.Now then it QuestionItem
public string Property1 {get; set; }
public string Property2 {get; set; }
...
public OldQuestionItem(NewQuestionItem newItem)
{
//logic to convert new in old
}
}
public class NewQuestionItem : OldQuestionItem
{
}
and use UploadTimeStamp as marker to understand, what Question is it.

Return a class of List objects from a wcf service and assign it on the Client

How do I return a class with List<T> objects from a wcf service to a client?
Can someone show me an example on how to return a class with some list objects and assign it to the client? I am getting this error on the client when I try to assign the class with Listobjects to local variables on the form
Error: Cannot implicitly convert type 'System.Collections.Generic.List<TesterWCFService.ServiceRef.TypeCode>' to 'System.Collections.Generic.List<Project1.TypeCode>'
Code:
public interface ICodesService
{
[OperationContract]
CodesList LoadCodeData();
}
[Serializable]
[DataContract]
public class CodesList
{
[DataMember]
public List<TypeCode> TypeCodes{ get; set; }
[DataMember]
public List<TypeCode1> TypeCodes1{ get; set; }
}
LoadCodes.svc
public class LoadCodesService : ICodesService
{
CodesList _AllCodes = new Codes();
public CodesList LoadCodeData() {
using (CodeEntities _codes = new CodeEntities()) {
_AllCodes.TypeCodes= _codes.TypeCode.ToList();
_AllCodes.TypeCodes1= _codes.TypeCodes.ToList();
}
return _AllCodes
}
}
On the Client:
public class Codes
{
public List<TypeCode> TypeCodes{ get; set; }
public List<TypeCode1> TypeCodes1{ get; set; }
}
This is the same class as CodesList on the ICodesService. I am declaring it at both placing ICodesService and the client. I want to be loading it on the webservice and assigning it on the client
private void button1_Click(object sender, EventArgs e)
{
public Codes _codesInProxy = new Codes();
LoadCodesServiceReference.CodesServiceClient proxy = new LoadCodesServiceReference.CodesServiceClient();
proxy.CodesList _codesList;
_codesList= proxy.LoadCodeData();//this one returns the codeslist from the service
_codesInProxy.TypeCodes = codesList.TypeCodes.ToList()
// This one gives an error
//Now I would like assign it to the class on the client and use it
}
Error: Cannot implicitly convert type 'System.Collections.Generic.List<TesterWCFService.ServiceRef.TypeCode>' to 'System.Collections.Generic.List<Project1.TypeCode>'
You can/should use the same object reference as that created in the WCF service.
The wcf service will expose the objects defined in the interface, and you should create you client side objects, as references of the WCF objects.
When adding the service reference, Visual Studio already creates all the empty class structures, you can just use them.
Pseudo Code:
New var as wcfserviceReferenceInstance.object
It seems that problem is that you have two different definitions for storing call resulton client side - one generated by adding WCF Service Reference (proxy.CodesList) and another defined manually (Codes).
You don't need to re-define server side classes once more in client side. If you add Service Reference then all the data types will be generated automatically. Just change client side so you use proxy.CodesList everywhere.

Put custom Class in ApplicationDataContainer in C# (WinRT)

I have a Windows 8 application. This application has several custom-defined classes. I need to store instances of these instances into Isolated Storage. From my understanding, Isolated Storage has been replaced with ApplicationDataContainer. Currently, I'm trying the following:
public class MyClass
{
private HttpClient service = new HttpClient();
public string FirstName { get; set; }
public DateTime? BirthDate { get; set; }
public int Gender { get; set; }
public async Task Save()
{
// Do stuff...
}
}
...
MyClass myInstance = new MyInstance();
// do stuff...
try {
ApplicationDataContainer storage = ApplicationData.Current.LocalSettings;
if (storage != null)
{
if (storage.Values.ContainsKey("MyKey"))
storage.Values["MyKey"] = myInstance;
else
storage.Values.Add("MyKey", myInstance);
}
} catch (Exception ex)
{
MessageDialog dialog = new MessageDialog("Unable to save to isolated storage");
dialog.ShowAsync();
}
What am I missing. Why is an exception always being thrown. The exception is not very descriptive. Its just a generic System.Exception and the message doesn't help either. Can someone please help me?
Thank you
The exception I get from the code above seems pretty clear:
Data of this type is not supported.
Per Accessing app data with the Windows Runtime
The Windows Runtime data types are supported for app settings.
Note that there is no binary type. If you need to store binary data, use an application file.
You can use the ApplicationDataCompositeValue class to group settings that must be treated atomically (but they still need to be supported runtime data types). Scenario 4 of the Application Data Sample covers this.
In your specific case though, you may want to consider serializing to a file and using app file storage versus settings.
I have implemented my ModelStorage framework for this scenario.

Serializing complex objects for WCF

I'm trying to pass a complex object via Windows Communication Foundation, but I get Read errors. I'm able to binaryFormat the object to a file and reload and deserialize it. All the components/ referenced component Classes are marked with the Serializable attribute. As a work round I have serialized the object to a memory stream, passed the memory stream over WCF and then deSerialized the memory stream at the other end. Although I could live with this solution it doesn't seem very neat. I can't seem to work out what the criteria are for being able to read from the proxy. Relatively simple objects, even ones that include a reference to another class can be be passed and read without any attribute at all. Any advice welcomed.
Edit: Unrecognised error 109 (0x6d) System.IO.IOException the Read Operation Failed.
Edited As Requested here's the class and the base class. Its pretty complicated that's why I didn't include code at the start, but it binary serializes fine.
[Serializable]
public class View : Descrip
{
//MsgSentCoreDel msgHandler;
public Charac playerCharac { get; internal set;}
KeyList<UnitV> unitVs;
public override IReadList<Unit> units { get { return unitVs; } }
public View(Scen scen, Charac playerCharacI /* , MsgSentCoreDel msgHandlerI */)
{
playerCharac = playerCharacI;
//msgHandler = msgHandlerI;
DateTime dateTimeI = scen.dateTime;
polities = new PolityList(this, scen.polities);
characs = new CharacList(this, scen.characs);
unitVs = new KeyList<UnitV>();
scen.unitCs.ForEach(i => unitVs.Add(new UnitV(this, i)));
if (scen.map is MapFlat)
map = new MapFlat(this, scen.map as MapFlat);
else
throw new Exception("Unknown map type in View constructor");
map.Copy(scen.map);
}
public void SendMsg(MsgCore msg)
{
msg.dateT = dateTime;
//msgHandler(msg);
}
}
And here's the base class:
[Serializable]
public abstract class Descrip
{
public DateTime dateTime { get; set; }
public MapStrat map { get; set; }
public CharacList characs { get; protected set; }
public PolityList polities { get; protected set; }
public abstract IReadList<Unit> units { get; }
public GridElList<Hex> hexs { get { return map.hexs; } }
public GridElList<HexSide> sides { get { return map.sides; } }
public Polity noPolity { get { return polities.none; } }
public double hexScale {get { return map.HexScale;}}
protected Descrip ()
{
}
public MapArea newMapArea()
{
return new MapArea(this, true);
}
}
I suggest that you take a look at the MSDN documentation for DataContracts in WCF since that provides some very helpful guidance.
Update
Based on the provided code and exception information, there are two areas of suspicion:
1) Collections and Dictionaries, especially those that are generics-based, always give the WCF client a hard time since it will not differentiate between two of these types of objects with what it considers to be the same signature. This will usually result in a deserialization error on the client, though, so this may not be your problem.
If it is your problem, I have outlined some of the steps to take on the client in my answer to this question.
2) You could have, somewhere in your hierarchy, an class that is not serializable.
If your WCF service is hosted in IIS, then the most invaluable tool that I have found for tracking down this kind of issue is the built-in WCF logger. To enable this logging, add the following to your web.config file in the main configuration section:
After you have generated the error, double-click on the svclog file and the Microsoft Service Trace Viewer will be launched. The items in red on the left-hand side are where exceptions occur and after selecting one, you can drill into its detail on the right hand side and it usually tells you exactly which item it had a problem with. Once we found this tool, tracking down these issues went from hours to minutes.
You should use DataContract and DataMember attributes to be explicit about which fields WCF should serialise, else also implement ISerializable and write (de-)serialisation yourself.

Categories

Resources