C# - Send a WinForm over TCP - c#

I have created a client server application which is currently able to send messages as containers:
[Serializable]
public class MsgContainer
{
public string TableName { get; set; }
public bool SomethingBool { get; set; }
public DataTable DataTableData { get; set; }
}
The problem: Depending on the request from the user I would like the server to be able to send Forms
public Form requestedForm { get; set; }
The problem with that (as i have read in the web and tried in my application) WinForms are not serializable which is why i receive the following error:
System.Runtime.Serialization.SerializationException: 'Type 'System.Windows.Forms.Form' in Assembly 'System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' is not marked as serializable.'
Is there any workaround to my problem?

I would strongly advise you find a different approach to whatever you're trying to do. The Form is not serializable. You could:
Make a serializable class to transfer all the form information and regenerate a form based on it.
Write your own serializer and deserializer for a form.
Either way you would need to overcome the many following issues, such as:
Components in the form are also not serializable.
Each control may have a value or a binding to a data source that also needs to be transferred.
You can include infinite different objects and classes in a form that would be part of your main project. Everything would need to be in a library consumed by both server and client.
Basically, this would be your worst nightmare and after spending however much time you may spend working on it, you will eventually realise that you have nothing but bin filler.

You cannot (reasonably) serialise a form.
A better approach, if viable, would be to build the forms into the client app. Then have the server instruct the client as to which form to open. Optionally use an enum for this.
public enum FormType
{
Products,
Customers
}
public FormType RequestedForm { get; set; }

Sending a Form is a pretty pointless excersise. Forms are just there to Display data. If you want a certain form to be dispalyed, send the Data it needs rather then the whole Form.
Honestly it sounds like you either have some very faulty design. Or wanted to do a WebApplication the whole time. Consider that you might be stuck in a XY Problem.

Related

Detecting Web vs Windows application

We have a library that is shared in .net between both Web and Windows (forms and console) applications. When used as a Web application, a couple of variables need to be read from cookies. Otherwise it needs to read the same variables from the Windows registry. I cannot seem to work out a good solution to doing this such that the same library compiles for all environments. Specifically, the web libraries for reading cookies would not be included in the Windows apps (and thus break the compile), let alone detecting one environment vs another. Does anyone have a solution to this?
If you host in IIS you can read Environment.GetEnvironmentVariables("APP_POOL_ID") and then act accordingly if the variable exists
Depending on architecture of your library, this information should be provided by the client code. I.e you provide some abstraction layer that will be up to client code to fill in.
I'll show a simple example of what I mean. In your library you have an interface like this:
public interface ISettingsProvider
{
public string GetSettingA();
public string GetSettingB();
}
And then your library code that needs access to settings will have to take a dependency on ISettingsProvider:
public class MyLibraryClient
{
private readonly ISettingsProvider settingsProvider;
public MyLibraryClient(ISettingsProvider settingsProvider)
{
this.settingsProvider = settingsProvider;
}
public void MyAwesomeMethod()
{
var settingA = settingsProvider.GetSettingA();
// do more stuff with your settings
}
}
Then your client code should implement ISettingsProvider:
public class WebSettingsProvider : ISettingsProvider
{
public string GetSettingA()
{
// go get the value from cookies
return Cookies["MyCookie1"];
}
public string GetSettingB()
{
// go get the value from cookies
return Cookies["MyCookie2"];
}
}
And very similar thing goes for settings stored in registry.
And when client code is accessing your library, they will have to instantite an instance of settings provider and give it to you.
This way your library does not know anything about web or Windows. You got to keep your code cleaner and it is all a lot more testable. And you don't have to take dependencies on System.Web and ultimately push that depdency on client code that does not work with web, i.e. Windows applications.
I know you have said you are limited in the amount of changes you can do. My answer to this is: you can't make an omlet without breaking eggs. This will be the most clean way to do what you want, everything else will have drawbacks.
In a Web-Environment you should have HttpContext.Current. If you are calling the same from the Console (or a WinForms-Application) this should be null instead of the Context.
To access this you need a reference to Sytem.Web. There should be no issue when you add this reference and access your backend from the Winforms-Application.
Example:
public bool ImInDaWeb() {
return System.Web.HttpContext.Current!=null;
}
Even in a web-application, HttpContext.Current can be null, but as you are needing this detection for reading/writing cookies you will have to detect this within a valid request already (and not on Application start for example).

Online chat solution for Asp.Net MVC 5.1 website

I have an Asp.Net MVC 5.1 website. We've got 3 types of users and I want to add support for chat between one type of them. I have thought of some models like this:
public class Conversation
{
public NormalUser A { get; set; }
public NormalUser B { get; set; }
public List<PrivateMessaage> Messages { get; set; }
}
public class PrivateMessaage
{
public NormalUser Sender { get; set; }
public NormalUser Receiver { get; set; }
public string Message { get; set; }
public DateTime Created { get; set; }
}
Also, I'm using SignalR in other parts of the project and thought like it's a very good solution to add the chat interface on top of the SignalR. Everything looks good so far. However, I think hitting the database to insert a new message EVERY time a message is being typed is not a good idea. I've created so many strategies to implement custom donut caching in my website to make every single page as fast as possible and it seems like this would cancel all of them out! What is the preferred solution to this problem? I think I might take some approaches like these:
Push them to the database in batches. For instance once a message is past a threshold (its date/time difference is more than X or the message count is more than Y).
Don't support offline messages, just push them in-memory to the other side through SignalR.
Same as the 2nd, but support offline when the target user is offline. I imagine not many messages will be sent to offline users!
Don't cache anything. I'll work out!!
One issue with the first one is that, there might be a situation where the website would go down (for update, power failure, apocalypse(!), etc.) and all the messages in memory would be lost. I can add a custom action to flush everything but it's never quite safe. Since there's a lot of chat solutions out there, I think there are very convenient solutions to this.
If you are not opposed to using other databases, realtime chat is extremely easy using Firebase and AngularJS.

Maintain a Dictionary with WCF RESTful Service

I need to write a RESTful WCF service that maintains a dictionary (or any other suitable data structure) with userId:userData as key:value pairs.
For that I first need to implement an interface for getting and setting userData (the specific configuration is enclosed):
GetConfiguration() : returns default config when user hasn’t set a config yet
GetConfiguration(string id)
SetConfiguration(string id, Configuration configurationSchema)
Then I'll need to write a service that implements this interface.
As a newbie in WCF I'm not sure how to do it. I tried to look for relevant references but didn't found any.
Appreciate any help/relevant references, Thanks !
The userData object:
public class ConfigurationSchema
{
public string MobileNumber { get; set; }
public List<string> Habits { get; set; }
public ConfigurationSchema(string mobileNumber, List<string> habits)
{
this.MobileNumber = mobileNumber;
this.Habits = habits;
}
}
may be below video will help you to create a WCF service. Once create simple WCF service after that add your code.
https://www.youtube.com/watch?v=GzN1vHWlJjA
If you did not find references to help you, I'd suggest you learn to google before you tackle programming problems. It's worth it. For your problem:
Open Visual Studio
Chose WCF project
Replace example complex data structure by your own class
Rename methods
Rename interface
Press F5

SharePoint WebPart Custom Settings - Best Practise

I'm trying to ascertain what the best practise is for creating a SharePoint WebPart that has custom properties. I'll detail the background, because I might be doing this in completely the wrong way.
I've taken a DevExpress chart, which has a whole host of settings on there. I then decided to expose some of these settings and ended up with a WebPart that looked like:
public class MyWebPart : WebPart
{
public DataTable { get; set; }
public String ConnectionString { get; set; }
public String Query { get; set; }
public override void DataBind()
{
UpdateMyTable(ConnectionString, Query);
this.chartControl.DataSource = this.DataTable;
}
}
I needed to add a whole load more settings onto this web part, a few single items that are strings, and others that correspond to a series (e.g. Binding values, Chart Type). So I moved the settings off the WebPart and ended up with something more akin to the following:
public class MyWebPart : WebPart
{
public DataTable { get; set; }
public ChartSettings { get; set; }
public override void DataBind()
{
UpdateMyTable(ConnectionString, Query);
this.chartControl.DataSource = this.DataTable;
}
}
public ChartSettings
{
public List<SeriesSettings> Series { get; set; }
}
I made my settings classes Serializable and added a Personalizable attribute on the Property on my web part. This works fine via the web.
If I attempt to open the page in SharePoint designer however it complains that it can't create a ChartSettings (and DataTable) from their String representations. I've learnt that this is because the settings are exposed as Strings. Obviously the DataTable I can suppress the serialization of.
My question ultimately is, am I following the correct approach, moving settings onto a class? Or should I be leaving all the settings on my webpart (which would be messy keeping lots of series settings in different arrays), or is there a completely different approach? If you can point me to any references to support your suggestion (e.g. MSDN) then that would be very much appreciated.
My personal experience (and some may disagree) has been to keep the WebPart as thin as possible. WebParts seem to be awkward for things like: configuration, error handling and logging, tracing, etc. I have found it much easier to put the bulk of my development into a WS (WebService/WCF) on localhost:8080. The code in the webpart is simple: call the WS and let it do all of the work. Config in the webpart is now simple because localhost is always easy to find. Dev tools for WS/WCF are very strong. Config, debugging, error handling, logging, tracing are all much simpler in WS/WCF. Better still, I make a simple jig (Winform/Webform) to call/test my WS layer. With this architecture, you put your code where your dev tools are strongest. It is similar to the rationale behind the MVC pattern.

MVC C# Web application

How do I edit information from an customer settings data model, which doesn't come from a database.
I've created a view which starts with
edit.aspx
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage" %>
Notice it contains MyApp.Models.LocationDisplayOptions. How can I save data on the form, which isn't linked to a database. I'm sorry if this isn't clear, but simply I need to save data not stored in a database.
namespace MyApp.Models
{
public class LocationDisplayOptions
{
public string Town { get; set; }
public string Country { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public LocationDisplayOptions()
{
// Some web url stuff
Town = dt.Rows[0]["City"].ToString();
Country = dt.Rows[0]["CountryCode"].ToString();
Latitude = System.Convert.ToDouble(dt.Rows[0]["Latitude"].ToString());
Longitude = System.Convert.ToDouble(dt.Rows[0]["Longitude"].ToString());
}
}
}
Why do you need to save it? What are you going to do with the data after you save it. That's going to really drive the answer.
If you just need to persist information from one view of the page to another, you can put it in a Session variable.
If you need to persist it longer than that, you could store it in a file on the web server, but if it is a high volume website, that can really slow things down.
You could consider a database. Microsoft SQL CE is a good option for small-footprint data stores, as it doesn't require any server-side installs-- just a DLL that goes along with the rest of your application.
Here's a link to ScottGu's post about SQL CE: http://weblogs.asp.net/scottgu/archive/2010/06/30/new-embedded-database-support-with-asp-net.aspx
Do you merely used drag and drop to work with databases, letting magic happen as far as editing of data is concerned?
While you can exist with LINQ to SQL or EF drag and drop, the "magic" underneath the hood is worthwhile to learn, especially in light of other forms of persistant mechanisms.
To persist to a file, you have to capture the form data and then create a class that handles the save to the file. The best path is to Google saving to the type of file (comma separated, XML, etc) and create the software to handle the persistance of that information. You can test it with a simple console app. When you are happy, use the same pattern to wire to your MVC application. The main difference is you have to get the path from the ASP.NET internals (hard coded == bad).
Someone may have an open source "module" that does this work, so search the open source sites.
Peace and Grace,
Greg
Twitter: #gbworld
Blog: http://gregorybeamer.wordpress.com

Categories

Resources