2

I don't have a problem, but I'm trying to prevent a problem from occurring in the future and would like a little help figuring out the proper way to approach this. I have a vendor who will be posting XML to a webpage that I have created. This would happen potentially every 2 minutes. The web page will then read the XML posted and insert into a Database. Serializing the XML and inserting is not good enough so I have to do a little bit of parsing before I send the data to the database. I created a static class that looks like the following.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// Summary description for Accounting
/// </summary>
public static class Accounting
{
    public static String currentFile = "";
    public static List<string> PurchaseOrder = new List<string>();
    public static List<string> item = new List<string>();
    public static List<string> unitPrice = new List<string>();
    public static List<string> shippingCharge = new List<string>();
    public static List<string> handlingCharge = new List<string>();
    public static List<string> discountAmount = new List<string>();
    public static List<string> UOM = new List<string>();
    public static List<string> invoiceNumber = new List<string>();
    public static List<string> supplierNumber = new List<string>(); //{ get; set; }
    public static List<string> supplierInvoiceNo = new List<string>();
    public static List<string> account = new List<string>();
    public static List<string> fund = new List<string>();
    public static List<string> org = new List<string>();
    public static List<string> prog = new List<string>();
    public static List<string> activity = new List<string>();
    public static List<string> location = new List<string>();
    public static List<string> distributionType = new List<string>();
    public static List<string> distributionValue = new List<string>();
    public static List<int> sequence = new List<int>();
    public static List<string> quantity = new List<string>();
    public static List<string> dueDate = new List<string>();
}

This class is static because I need to operate on the variables from different methods. Now here is where things get tricky, I keep reading that if I use static variable in a .NET web application I will end up sharing the variable across sessions. This could potentially be a nightmare for me. so I looked into the singleton pattern and I have also found this Static variables in web applications solution throught stackover flow. I read that I should do something like this

public class SingletonPerRequest
{
    public static SingletonPerRequest Current
    {
        get
        {
            return (HttpContext.Current.Items["SingletonPerRequest"] ??
                (HttpContext.Current.Items["SingletonPerRequest"] = 
                new SingletonPerRequest())) as SingletonPerRequest;

        }
    }
}

My problem is that I don't know how can I convert my class to basically do what the above is doing. In other words how do I set class to follow this singleton request pattern. Forgive my stupidity if this does not make sense. My ultimate goal would be to have every request to the page have its own session of accounting variables and not get shared across session. Any help would be greatly appreciated.

Community
  • 1
  • 1
Miguel
  • 2,019
  • 4
  • 29
  • 53
  • If you don't want anything shared between requests, why not just avoid using static and use an actual instance? Create the instance, and pass it as a parameter to the methods that need to access the data. – Pablo Romeo Dec 07 '14 at 17:31

2 Answers2

1

Here is your class:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

public class Accounting
{
    public static Accounting Current
    {
        get
        {
            return (HttpContext.Current.Items["Accounting"] ??
                (HttpContext.Current.Items["Accounting"] = 
                new Accounting())) as Accounting;

        }
    }

    public String currentFile = "";
    public List<string> PurchaseOrder = new List<string>();
    public List<string> item = new List<string>();
    public List<string> unitPrice = new List<string>();
    public List<string> shippingCharge = new List<string>();
    public List<string> handlingCharge = new List<string>();
    public List<string> discountAmount = new List<string>();
    public List<string> UOM = new List<string>();
    public List<string> invoiceNumber = new List<string>();
    public List<string> supplierNumber = new List<string>(); //{ get; set; }
    public List<string> supplierInvoiceNo = new List<string>();
    public List<string> account = new List<string>();
    public List<string> fund = new List<string>();
    public List<string> org = new List<string>();
    public List<string> prog = new List<string>();
    public List<string> activity = new List<string>();
    public List<string> location = new List<string>();
    public List<string> distributionType = new List<string>();
    public List<string> distributionValue = new List<string>();
    public List<int> sequence = new List<int>();
    public List<string> quantity = new List<string>();
    public List<string> dueDate = new List<string>();
}

You can use the singleton like that: Accounting::Current.quantity

Note:

Using a static class is an antipattern in OOP. A static class is like a namespaced collection of method. You cannot instantiate objects that preventing you from using inheritance, interfaces, low coupling, dependency injection, ... Always use a singleton instead. This will help you to make a better architecture. You also should take a look at SOA (Service Oriented Architecture) in OOP and then in HTTP (REST webservices).

Gnucki
  • 5,043
  • 2
  • 29
  • 44
  • Gnucki, so in essence every request would get a unique instance of accounting, right? that's what Im worry about. I'm worry that if one request comes in first and has not finished and then a second request comes in behind it and start operating on the accounting class it would potentially have awkward results. – Miguel Dec 07 '14 at 17:29
  • Yes, there will be only one instance of `Accounting` for a same request. As the context is linked to one only request, this instance won't be shared between requests and so between users. Just open 2 pages of your website to test it! – Gnucki Dec 07 '14 at 17:33
  • This is a good implementation of a Singleton. I just wanted to note that it assumes there's only one web server. If you have multiple servers, you would need to employ additional tactics to ensure both servers use the same object. – neontapir Dec 07 '14 at 17:39
  • No this object is a singleton on a request basis and not on a user basis. – Gnucki Dec 07 '14 at 17:41
  • I stand by my statement. Two IIS web servers won't share the same HttpContext object, so a value in one won't be seen by the other. This is why a lot of web farms use sticky sessions, so that the same server always responds to a particular user. – neontapir Dec 07 '14 at 17:56
  • Of course, the session must be shared between all the servers! – Gnucki Dec 07 '14 at 18:15
  • But I think that HttpContext.Current is bound to the request and not the session. It seems to me that the session is in HttpContext.Session but I'm not an expert in .NET web developement. – Gnucki Dec 07 '14 at 18:24
0

The Singleton pattern is used to ensure a single instance of an object is shared across an entire application, so it sounds like the opposite of what you are trying to achieve.

In the latter half of your question, it sounds like you want a separate instance for each request, which is essentially how ASP.NET handles objects by default (read up on Page.Load and Unload on the ASP.NET lifecycle overview page for details).

If that's the case, you should not need to do anything special except convert this from a static class to a normal class. What behavior are you seeing?

As an aside, you may want to look into Linq for Xml, which is built into the framework and could simplify your XML parsing. With Linq, you could potentially get rid of the need for many of those static variables by using XML queries to retrieve data.

neontapir
  • 4,698
  • 3
  • 37
  • 52
  • Thanks Neontapir I'm just afraid that if two request come in simultaneously I would end up possibly overridden the list of string by the second request. I'm not seeing anything strange yet but I'm trying to prevent any problems from occurring in the future. – Miguel Dec 07 '14 at 17:26
  • As the lifecycle documentation demonstrates, a new copy of the Page class is created upon each request. – neontapir Dec 07 '14 at 17:35
  • yes but static classes are shared across user sessions. That's the problem that I can potentially encountered. Atleast that's what I'm reading from http://stackoverflow.com/questions/14154892/scope-of-static-variable-in-multi-user-asp-net-web-application – Miguel Dec 07 '14 at 17:38
  • Correct, hadn't noticed that your class was static. With a static class, you get a new object once on first load. I edited my answer. For a new object per request, just remove the static keywords. – neontapir Dec 07 '14 at 17:42
  • neontapir I wanted to take advantage of the static variable and also have them not be shared across request. It appears that the code above By Gnucki gets me that. – Miguel Dec 07 '14 at 17:47