C# Web Service and Global Variables - c#

I'm having a problem getting my global variables to work on my client application.
In the web service, I have the following code:
public class MyWebService: System.Web.Services.WebService
{
public static string test = String.Empty;
....
On my client side I have this code:
MyService.MyWebService client = new MyService.MyWebService()
{
client.test="test";
};
On the client side I'm receiving
"MyWebService does not contain a definition for test...etc";
Can you use global variables within a web service? Any help would be appreciated.
Thanks!

You'll have to expose getter (and or setter) in webservice in order to be visible for client. i.e:
public class MyWebService: System.Web.Services.WebService
{
public static string test = String.Empty;
public string GetTest() {
return test;
}
public void SetTest(string test) {
MyWebService.test = test;
}
}
Also read some topic on thread-safety, if you're planning to have more clients simultaneously.

Even though it may look like you're actually using classes when invoking web services, you're not. Web services do not know the concept of variables. All you can do is invoke methods.

Related

How to create a global variable in ASP.NET Core Web API application?

How can I create a global variable in an ASP.NET Core Web API application? In ASP.NET MVC, I could do it like:
Application["<variableName>"] = <value>
I tried the same in my web API application, but was unable to find an equivalent for this. I saw some solutions which suggested me to store the data appsettings.json, but since the data I want to store in the global variable is not static, I cannot use that setup. I need to set different data during runtime. How can I do that? Please help me.
We could use Singleton_pattern , creating an Application static object in .net core.
we can also try to use Depend Injection, register a singleton object as below in your code.
Writing a property ConcurrentDictionary in ApplicationInstance class.
public class ApplicationInstance {
public ConcurrentDictionary<string,object> Application { get; } = new ConcurrentDictionary<string, object>();
}
public void ConfigureServices(IServiceCollection services){
services.AddSingleton<ApplicationInstance>();
}
Then we might use this object
public class HomeController : ControllerBase
{
private readonly ApplicationInstance _application;
public HomeController(ApplicationInstance application)
{
this._application = application;
}
//use _application["test"] instance in your code
}
I would use ConcurrentDictionary to help us avoid racing-condition which will be happened on multiple-thread accessing the same object concurrently.
somewhere in project
public static class Config{
public static Dictionary<string,string> Application = new Dictionary<string,string>();
}
elsewhere
Config.Application["froop"] = "noodle";
of course you will have to deal with race conditions, etc
First of all thank you all for finding some time to help me. I took #pm100's solution and made a slight modification to suit my purpose. I could not use it directly as I am using SonarLint, and it had some issues, so I used a KeyValuePair instead of Dictionary like this:
public static class GlobalData
{
public static KeyValuePair<string,object> Application { get; set; }
}
and I used it in my code like:
string value = GlobalData.Application.Value
and luckily it works without any issue.

Managing dynamic Urls in ASP.NET Core

I am consuming third party APIs in which I fetch base URL from my configuration file (appsettings.json).
While creating dynamic endpoints I concatenate URL as follows:
$"{BaseUrl}/api/v1/users/{id}/apps"
Now problem is I got feedbacks on this as hardcoding and it is also hard to maintain for future modifications.
Is there any better approach for managing third party APIs endpoint or URLs?
Use static class to manage URLs.
static class ApiRoutes {
private const string Base = "Api"
Private static Class ControllerOne {
public static string Get = Base +"\ControllerOne\{id}"
public static string Post = Base +"\ControllerOne\{id}"
}
Than In your Controller,
You can do something like that:
[httpGet (ApiRoutes.ControllerOne.Get)]
Get (string something) {
/*your code*/
}
[httpPost(ApiRoutes.ControllerOne.Post)]
Post (string something) {
/*Your code*/
}
Then, if you will have the desire to change the URL in the future, it will be much easier!

accessing multi endpoints web services (ASMX) best practices in c#

I have a clean architecture project that provide micro services, one of which is to access Agresso ERP web services.
https://***************/service.svc
it provide many services
https://**/service.svc?FooService/Foo
https://**/service.svc?BooService/Boo
each of which has it's own service reference(connected service), and each of which has many methods.
each call to any of the end point you need to pass credentials with it.
var fooSoapClient = new FooSoapClient();
var credentials = new WSCredentials
{
Username = "fakeuser",
Password = "fakepassword",
Client = "fakeclient",
};
var result = fooSoapClient.GetFoosAsync(Foo filter,true,
credentials );
(P.S) credential class exist in all entities
namespace Foo1NS
{
public partial class WSCredentials : object
{
public string Username {get;set;}
public string Client {get;set;}
public string Password {get;set;}
}
}
namespace Foo2NS
{
public partial class WSCredentials : object
{
public string Username {get;set;}
public string Client {get;set;}
public string Password {get;set;}
}
}
i can access all end points with no problem.
I have the following Questions:
Is there a generic solution i can follow for not to Fall in DRY?
is there a design pattern that best target this issue?
Here is what I've done in the past, it fits in well into Dependency Injection/containers if you use that as well. The key thing here is to define an single interface that all services will implement. Your code that uses this should only be using the interface.
Each class should implement an interface you define, e.g. IWebServiceOperations
public interface IWebServiceOperations
{
WebServiceOperationResult GetFooAsync(WebServiceOperationRequest request);
}
I'll leave you to figure out the classes WebServiceOperationResult/Request, they just hold your request/response variables, including credentials.
Then each webservice you need to implement is done in a separate class. You also dictate in the constructor what type of implementation this is (FooSoap1 vs FooSoap2) e.g.
public class FooSoapClient : BaseClient, IWebServiceOperations
{
public FooSoapClient() : base(Clients.FooSoap1)
public GetFooAsync(...)
{
...
}
}
public class BaseClient
{
private readonly eFooServiceType _serviceType;
public eFooServiceType ServiceType {
get{
return _serviceType;
}
}
protected BaseClient(eFooServiceType service)
{
_serviceType = service;
}
}
Now you should have a bunch of class references. Either your DI container can resolve these for you, based on the service type you want, or you could add them to a Dictionary, so if you wanted to operate against FooSoap1, you'd do...
var fooSoapClient1 = myServices[Clients.FooSoap1];
await fooSoapClient1.GetFooAsync(...)

The channeldispatcher is unable to open its ichannellistener

I am starting out with WCF. I have created two console apps (server and client) that work without any issues but since moving them onto forms I'm having all kinds of problems. I had a look here and elsewhere on the net, I can't seem to find anything that can help me with my issue. I honestly don't understand the issue but I think it may have something to do with my datatypes (they're under different namespaces)?
Here's my Server code:
public partial class Form1 : Form
{
ModelDataServer Server;
public ScraperForm()
{
InitializeComponent();
Server = new ModelDataServer(); // Opened Here
Server.Scraper = this;
}
}
[ServiceContract]
public interface IModelData
{
[OperationContract]
ArrayList GetData();
}
[ServiceBehavior(UseSynchronizationContext=false)]
public class ModelDataServer : IModelData
{
ServiceHost Host;
public DataModel Model { private get; set; }
public ModelDataServer()
{
Host = new ServiceHost(typeof (ModelDataServer),
new Uri[]
{
new Uri("http://localhost:8000")
});
Host.AddServiceEndpoint(typeof(IModelData),
new BasicHttpBinding(),
"ModelData");
Host.Open(); // Error Points Here!!!
}
public ArrayList GetData()
{
return Model.GetData();
}
public void CloseServer()
{
Host.Close();
}
}
Here's my Client code:
[ServiceContract]
public interface IModelData
{
[OperationContract]
ArrayList GetData();
}
[ServiceBehavior(UseSynchronizationContext = false)]
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();
}
}
Here's the error I'm recieving (points to where I'm opening the ServiceHost):
The ChannelDispatcher at 'http://localhost:8000/ModelData' with contract(s) '"IModelData"' is unable to open its IChannelListener.
P.S. I have been struggling to get delegates to work outside of something I've done in a tutorial. If anyone can suggest a better way that uses delegates instead of passing my form class into the other class that would be great.
Yes, this is most likely related to namespace issues. For illustration issues, let's assume your server project's namespace is ServerApp, and your client's namespace is ClientApp. You define IModelData in both applications, which means you have ServerApp.IModelData and ClientApp.IModelData. Even though the code is identical, these are two separate interfaces (because of the namespace).
So you're trying to pass ClientApp.IModelData to the service, and it's expecting ServerApp.IModelData.
You can solve this by moving the interface IModelData to its own assembly and having the server app and the client app both reference this third assembly. That's what we do at work - all of our service contracts are in a separate assembly (two, actually, but that's a different story).
A couple of other things to note:
Unless your client is also hosting a service, you can remove the [ServiceContract] attribute from the class. Clients don't need that.
In your server app, what is Server.Scraper = this; for? It appears to be assigning the Form to a property Scraper in the service, but I don't see that property in your code. Additionally, services don't really use properties (I think I saw somewhere that you could do it, but it wasn't intuitive). I don't think you'd want to assign the entire form to the service, as service's in and of themselves don't usually have UIs - they supply data and receive data from the service.

WCF Per Instance

I have a WCF service code like this:
[ServiceContract]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple)]
public class SomeService
{
public string Password { [OperationContract] get; [OperationContract] set; }
public void CheckPassword()
{
if (Password == null || Password != "password")
throw new FaultException("Invalid Password");
}
[OperationContract]
public string SomeMethod()
{
this.CheckPassword();
return "Some Data";
}
}
And the client windows application consumes it like this:
public class ClientClass
{
public ClientClass()
{
STASomeService.Value.SomeMethod();
}
}
public class ClientClass
{
public ClientClass()
{
STASomeService.Value.set_Password("password");
}
}
How can I reset the value of SomeService.Password whenever the SomeService class is instantiated? I do not want an attacker to access my service methods, but when the actual client set the password, the passwords stays in the SomeService.Password property in every service call. But I want to retain the Password value per instance because the client needs that.
My code is in C#, framework 4, build in VS2010 Pro.
Please help. Thanks in advance.
You shouldn't have to reset the value of SomeService.Password because it isn't static. Are you seeing something to the contrary?
Since you're using InstanceContextMode.Single (which I originally overlooked), your best recourse my be to mock the behavior of having individual instances in your network bound singleton. The only way I can think of to facilitate this is to have a proxy service class that matches your service's contracts and delegates its calls to custom instances based on specific criteria (which would define the session). It would be cumbersome to maintain this way and adds a unnecessary level of abstraction, but (in my head at least) it should work

Categories

Resources