System.Web.Services.WebService - Is it possible to isolate a service on a client

I have an obsolete System.Web.Services.WebService (not WCF) that I have to support.

Mutual Assistance I encounter some wired behaviors, which I would call race conditions.

  • Either the service freezes or it needs to be restarted.

  • Sometimes I get this exception:

    System.NotSupportedException: Multiple simultaneous connections or connections with different connection strings inside the same transaction are not currently supported. at MySql.Data.MySqlClient.MySqlConnection.Open() ... 

I know the reason. The service uses lib, which speaks with mysql and was not designed for web services. Unfortunately, I cannot change this library.

One example web method is as follows:

 [WebMethod(EnableSession = true)] public void DoSomething() { var login = this.Session["login"] as LoginDetails; ExternalLib.SetLoginData(login.Schema, login.User, login.Pass); ExternalLib.PerformTask(); } 

So the problem is this:

  • ExternalLib.SetLoginData just set some global vars
  • ExternalLib.PerformTask makes database calls, some inside a transaction.
  • The process is similar to 1. Create MySqlConnection or take it from cache 2. Create MySqlCommand 3. Execute Command 4. Dispose command

Client a) calls DoSomething() , and I initiate its connection. Half way with his work, Client b) calls DoSomething() , which apparently changes the Login-Data for client a, and the next call inside the transaction will use the login from client b), which causes the transaction.

Anyway, I know this is a bad design, but my question is how to do it. Currently (since I only have 10 clients) I have created a dedicated site on the differnet port, which points to the same root directory, but this is a solution for akward.

It may be possible to run each session within your area. Any suggestions. If I understand this page correctly for WCF, this is the default behavior: http://msdn.microsoft.com/en-us/magazine/cc163590.aspx

Call services
Call Forwarding is Windows Communication's default instance creation mode. When a service type is configured to activate for each call, a service instance common (CLR) exists only when the client call is in progress. Each client request receives a new dedicated service instance.

0
source share
2 answers

Seeing that this is probably a thread issue, you can block ExternalLib so that individual instances do not call code.

 public class ExtenalLibWrapper { private static object Locker = new object(); public void DoSomething(LoginDetails details) { lock(Locker) { ExternalLib.SetLoginData(login.Schema, login.User, login.pass); ExternalLib.PerformTask(); } } } 
0
source

I have already wrapped all my public methods in a neat runtime wrapper to provide global exception logging.

This forces my web service to process one request after another, but, as I mentioned, max. number of simultaneous clients - 10

 public class MyService : System.Web.Services.WebService { [WebMethod(EnableSession = true)] public static int Add(int value1, int value2) { return Execute(() => { var calculator = new Calculator(); return calculator.Add(value1, value2); }); } private static Logger logger = LogManager.GetLogger(typeof(MyService).Name); private static System.Threading.SemaphoreSlim ss = new System.Threading.SemaphoreSlim(1, 1); private void Execute(Action method) { ss.Wait(); try { method.Invoke(); } catch (Exception ex) { logger.FatalException(method.Method + " failed", ex); throw; } finally { ss.Release(); } } private T Execute<T>(Func<T> method) { ss.Wait(); try { return method.Invoke(); } catch (Exception ex) { logger.FatalException(method.Method + " failed", ex); throw; } finally { ss.Release(); } } } 
0
source

Source: https://habr.com/ru/post/1012931/


All Articles