I have a linux c++ client (via gSOAP) to WCF c# server. The WCF c# service contains list of objects, on which some action is executed. Each time i call some function on service, the new object is created, action on that object is executed and that object lands into list in service. at the end i am calling another function on service, which loops over all objects in a list and executes another call on them. this works as intended on c#, with both client and service pure WCF.
it works different via gSOAP. each time i call a first function on service via gSOAP, that action is executed and list is updated. but it is each time new service. so basically i am dealing each time with new service. i do not wont serialize/deserialize object itself, to have it on inux side.
any ideas how to solve this?
on c# side i have something like (unnecessery details skipped)
class Service : IService
{
List list = new List();
void func1(int i)
{
Class1 c = new Class1(i);
c.create();
list.Add(c);
}
void func2()
{
foreach(Class1 c in list)
{
c.close();
}
}
}
on gSOAP side i have something like
Proxy service (endpoint);
service.func1(1);
service.func1(2);
//...
service.func2();
as i said problem is: when func2() is executed it operates on empty list, meaning gSOAP object of Proxy service does not contain c# object of service.
Help, help!
ps.
the solution is found: container made "static" does the trick.
Related
How to inject the [IServiceProvider] interface into custom services? I mean after the [Startup] class finishes construction of [IServiceProvider] from [IServiceCollection] set of bindings. How do I then subscribe to the newly created [IServiceProvider] built after method [ConfigureServices] invoked?
If you want to call your service inside startup you should create a scope
// initial database
using (var scope = app.ApplicationServices.CreateScope())
{
var initDatabase = new YourClass(scope.ServiceProvider.GetService<YourServiceInterface>());
}
But Accessing to IServiceProvider in other services don't make sense. If you describe more You could get the right answer.
I have a Website that contains a number of webpages and some WCF services.
I have a logging IHttpModule which subscribes to PreRequestHandlerExecute and sets a number of log4net MDC variables such as:
MDC.Set("path", HttpContext.Current.Request.Path);
string ip = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if(string.IsNullOrWhiteSpace(ip))
ip = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
MDC.Set("ip", ip);
This module works well for my aspx pages.
To enable the module to work with WCF I have set aspNetCompatibilityEnabled="true" in the web.config and RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed on the service.
But when the service method is called the MDC no longer contains any of the set values. I have confirmed they are being set by putting a logging method in the PreRequestHandlerExecute.
I think the MDC is loosing the values because in the log I can see the PreRequestHandlerExecute handler method and service method calls are on separate
threads.
The post log4net using ThreadContext.Properties in wcf PerSession service suggests using log4net.GlobalContext but I think that solution would run into issues if two users hit the application at the same time as GlobalContext is shared by all threads.
Is there a way to make this work?
Rather than taking the values from the HttpContext and storing them in one of log4net's context objects, why not log the values directly from the HttpContext? See my answer to the linked question for some techniques that might work for you.
Capture username with log4net
If you go to the bottom of my answer, you will find what might be the best solution. Write an HttpContext value provider object that you can put in log4net's GlobalDiagnosticContext.
For example, you might do something like this (untested)
public class HttpContextValueProvider
{
private string name;
public HttpContextValueProvider(string name)
{
this.name = name.ToLower();
}
public override string ToString()
{
if (HttpContext.Current == null) return "";
var context = HttpContext.Current;
switch (name)
{
case "path":
return context.Request.Path;
case "user"
if (context.User != null && context.User.Identity.IsAuthenticated)
return context.User.Identity.Name;
case "ip":
string ip = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if(string.IsNullOrWhiteSpace(ip))
ip = context.Request.ServerVariables["REMOTE_ADDR"];
return ip;
default:
return context.Items[name];
}
return "";
}
}
In the default clause I assume the name, if it is not a specifically case that we want to handle, represents a value in the HttpContext.Current.Items dictionary. You could make it more generic by also adding the ability to access Request.ServerVariables and/or other HttpContext information.
You would use this object like so:
Somewhere in your program/web site/service, add some instances of the object to log4net's global dictionary. When log4net resolves the value from the dictionary, it will call ToString before logging the value.
GDC.Set("path", new HttpContextValueProvider("path"));
GDC.Set("ip", new HttpContextValueProvider("ip"));
Note, you are using log4net's global dictionary, but the objects that you are putting in the dictionary are essentially wrappers around the HttpContext.Current object, so you will always be getting the information for the current request, even if you are handling simultaneous requests.
Good luck!
I have Server and Client.
The client call a method on the server, The server in response have to prepare a Dictionary and send back to client.
This operation might take time.
It should be async. I read instructions and examples.
Mostly the BeginXXX and EndXXX IAsyncResult. But If i need the server to return Dictionary of objects. How do i implement this ?
I thought when sending a callback delegate I can send a signature of one of the clients' functions as delegate and when Server finish it will invoke the delegate with the proper dictionary data.
1) Adding service reference in VS (or SLSvcUtil) generates handy proxy code with events for Silverlight projects. You can use it to implement callback's pattern for your 'service/server agent' if you want. You can use this code with regular .net apps as well with some modifications.
2) VS for .Net project can generate proxy with async methods. SvcUtil - too.
3) For real long running operations you can use WCF services with callbacks (+ some binding restrictions).
If I understand you in a right way, you're asking about this (based on eLibrary project):
WCF Server side:
EBooksLibraryEntities ebe = new EBooksLibraryEntities();
public List<Book> tabBooks()
{
return ebe.Books.ToList();
}
Client side:
ServiceReference1.Service1Client sr = new ServiceReference1.Service1Client();
List<ServiceReference1.Book> llb = new List<ServiceReference1.Book>();
private void GetBooksByAuthor()
{
sr.tabBooksByAuthorCompleted += new EventHandler<ServiceReference1.tabBooksByAuthorCompletedEventArgs>(sr_tabBooksByAuthorCompleted);
sr.tabBooksByAuthorAsync();
}
void sr_tabBooksByAuthorCompleted(object sender, ServiceReference1.tabBooksByAuthorCompletedEventArgs e)
{
foreach (var item in e.Result)
{
yourList.Add(item);
}
}
Some months back I was working on a project to display the WCF methods and thier parameters in a dropdown. At that time I was creating a proxy using Add Service Reference and hardcoded the service interface in the code.
How can I show all the methods that are available in my WCF in a dropdown
But when I try to create the proxy dynamically to do the same, the below code doesn't work. Please help me to show only the methods that was defined by me.
// Using Dynamic Proxy Factory by Vipul Modi # Microsoft
DynamicProxyFactory factory = new DynamicProxyFactory(txtService.Text);
// endpoints.
string sContract = "";
foreach (ServiceEndpoint endpoint in factory.Endpoints)
{
sContract = endpoint.Contract.Name; //this is the service interface name, IAccountInfoService
}
DynamicProxy proxy = factory.CreateProxy(sContract);
Type proxyType = proxy.ProxyType;
MethodInfo[] methods = proxyType.GetMethods();
foreach (var method in methods)
{
//if (method.GetCustomAttributes(typeof(OperationContractAttribute), true).Length == 0)
// continue;
string methodName = method.Name;
ddlMethods.Items.Add(methodName);
}
The code commented method.GetCustomAttributes(typeof(OperationContractAttribute), true).Length doesn't work. It doesn't show any method. If I comment it out, then the result is all methods and variables. I want to restrict it to only user defined methods.
i dont know anything about DynamicProxyFactory but looking at http://blogs.msdn.com/b/vipulmodi/archive/2006/11/16/dynamic-programming-with-wcf.aspx it makes me think that
1) the proxy doesnt actually emit methods with the attribute. it doesn't seem to have a need to though i suppose you could tweak the code on your own to make that happen.
2) if you just want a list of method names, it seems you can get that from factory.Contracts
I would like a method on my in my domain service similar to:
public SystemState GetSystemStatus()
{
return new SystemStatus
{
InterestingStatusValue1 = 1223,
OtherInterstingStatusValue = "abc",
}
}
That doesn't work. Nothing is auto-generated for the Silverlight client app. Howerver if I make this an IQueryable method, then I get something generated on the client. I'll get a SystemStates property and a Query method on the context object.
Is there no way to make this a simple WCF call? I suppose I could a WCF Silverlight Enabled service to my RIA Web site, and then setting a Service Reference (that can't be right?) (and why can't I see the Services Reference in the Silverlight app?)
On first blush it seems that RIA services forces a very data-centric/easy CRUD which is great for table editors, but not so much for LOB applications that go behind drag on a datagrid and you're done.
You can return just one entity using an attribute (assuming that SystemState is your entity):
Ex:
[Query(IsComposable = false)]
public SystemState GetSystemStatus()
{
return new SystemStatus
{
InterestingStatusValue1 = 1223,
OtherInterstingStatusValue = "abc",
}
}
Remember that this is still a query and Ria Services will generate a method in your DomainContext like:
EntityQuery<SystemState> GetSystemStatusQuery()
Use it like a normal EntityQuery, but keep in mind that you can't perform query operations (sorting or filtering) on the returned object.
If you want to execute an operation on server, try using the [Invoke] attribute. Ex:
[Invoke]
public SystemState GetSystemStatus()
{
return new SystemStatus
{
InterestingStatusValue1 = 1223,
OtherInterstingStatusValue = "abc",
}
}
I don't know how complex your return type can be, but I guess if it can be serialized, it will work (not sure).