Avatar of Ervik
Ervik
 asked on

IIS return wrong page

I have a strange problem which I hope someone can help me solve.
I run a webshop and has just made a replement page for a main page (order confirm) at the webstore. The original page was named order.aspx, and my replasement was named order2.aspx. And we then routet to this new page when we switched. And removed the old page from the project, in Visual Studio 2010, compiled and deployed.

After good amount of testing on two testing webserververs IIS 6.0 and IIS 7.0 it was rolled out on our production server (which use IIS 6.0 on Windows server 2003). Everything seems fine, and we get feedback of how mucht better this page has been. But suddently, we get som alarming feedback. Some customers claim that they could see other customers shopping charts. (Which is not so good since they would also be able to see the discount other have on some products.) The website has around 1000 simultan users, and we get report on this error 0 - 3 times pr. day.

We could reproduce this behavior when we set something on the page to not validate, and keep sending (pressing the submit button) several times. At some time we have to press 8 - 15 times to get a bogus page back. At some time we never get bogus page, and we also some times could get the bogus page with just 2 - 4 submits.

We was never able to reproduce this on any test envoironment. We have to roll back to use the old order.aspx page, and the problem went away. But we really want to use this new version that fixes many other problems that was in the original page.

We have found that a probe is running every 8th minute to check that the website is up and running. And this script calls the old order.aspx page, that was not removed from the server, but is just markup, and no code, since the old order.aspx page was removed from the project befor compilation and deployment. (The old order.aspx pages markup was also left on the testsites where we could not reproduce the error.)

Is there any way the IIS could be tricked to return somthing if the probe tried to call the old order.aspx markup?
Or can any one see an other plausible sulution on this case?
Microsoft Legacy OSMicrosoft DevelopmentMicrosoft Server AppsCOBOL

Avatar of undefined
Last Comment
Ervik

8/22/2022 - Mon
Ted Bouskill

If one user can see another users information that can mean only one thing.  Some data is being stored in a static variable.  On the test/development environment you might not be running into a peak load that is causing a problem with it.  Look through the code thoroughly.  You should NOT be using static for any data that is applied to a specific user.
Ervik

ASKER
There is no static varibles on the page that post to the sever, where the error occurs.
There are a few static function in the system, mosty on the datalayer.
I seach for static variables in the whole sulution and found one strin array in the datalayer:

private static readonly string[] AllFacetFields = new[] { "Leverandør", "Hovedgruppe" };

I really can't see that this could be the culpit? (Leverandør means Vendor and Hovedgruppe mens maingroup.)

The system consist of several layers. (Database, DataService, BusinessRules, BusinessFacade, BusinessEnities and Web. The Web prosject consist of the markup and codebehind classes that is the actual web pages. The system is built on .net 1.1 and later converte to .net 4.0. It uses frames. On the order page only two other frames are present. The top frame, that shows the top meny and the current users, and the left frame that shows the menu.
Ted Bouskill

Any static function can cause problems if it has any results specific to a user even temporarily in a database access layer.  Remember each page request is stateless and the only way to maintain state is via a session and/or static objects that are shared while two requests are occurring concurrently.

Therefore if you have two users see the same data then it has to be a shared static session variable or a static object.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
Ervik

ASKER
I don't know if two users sees the same data, only that one user can sometime see a page that contains info that is not for this user, but for a different user.

I have now gone through all static functions, but none of them are changed between the version that do not return wrong data, and the new version that sometimes return wrong data.

If a static function was the culpit, should't we get the same error even from the old posting page, or could there be a differense here?
Ted Bouskill

Not necessarily.  Sometimes you change the workflow and load enough that the error will become more apparent.

If UserA can see the data for UserB then it is the 'Same' data.  Sorry for not making that clear.
Ervik

ASKER
We have a class:  public class EntityMapper  which have serveral static functions like:

public static Order CopyToOrderDto(OrderEntity source) {
      Order target=new Order();
      target.Address=source.Address;
      target.CustomerId=source.CustomerId;
      target.DeliveryDate=source.DeliveryDate;
      target.OrderDate=source.OrderDate;
      target.OrderId=source.OrderId;
      target.OrderValue=source.OrderValue;
      target.PostalCode=source.PostalCode;
      target.ProjectDescription=source.ProjectDescription;
      target.ProjectID=source.ProjectID;
      target.ReferenceLabel=source.ReferenceLabel;
      target.ReferenceNo=source.ReferenceNo;
      target.ReferenceText=source.ReferenceText;
      target.ShowAlternativProduct=source.ShowAlternativProduct;
      target.ShowDiscount=source.ShowDiscount;
      target.TransportNotice=source.TransportNotice;
      target.UserID=source.UserID;
      target.UserName=source.UserName;

            target.AddressCo = source.AddressCo;
            target.CustomerProjectId = source.CustomerProjectId;
            target.CustomerOrderId = source.CustomerOrderId;
            target.CustomerDepartment = source.CustomerDepartment;
            target.CustomerMobilePhone = source.CustomerMobilePhone;
            target.CustomerEmployeeId = source.CustomerEmployeeId;
            target.CustomerWarehouse = source.CustomerWarehouse;
            target.CustomerReference = source.CustomerReference;
            target.OrderConfirmationCode = source.OrderConfirmationCode;
            target.OrderConfirmationFaxNo = source.OrderConfirmationFaxNo;
            target.CustomerEmail = source.CustomerEmail;
            if (source.DeliveryType == 2)
            {
      target.FirstPriorityWarehouseCode = source.ProffMarketCode;
      target.ShippingMethodCodeForFirstPriorityWarehouse = "HE";
            }
                  ArrayList orderItems=new ArrayList();
      foreach (OrderItemEntity orderItem in source.OrderItems) {
            orderItems.Add(CopyToOrderItemDto(orderItem));
            if (string.IsNullOrEmpty(orderItem.Comment) == false)
            {
            OrderItemEntity commentOrderItem = new OrderItemEntity();
            commentOrderItem.ProductId = "20";
            commentOrderItem.Description = orderItem.Comment;
            orderItems.Add(CopyToOrderItemDto(commentOrderItem));
            }
      }
      target.OrderItems=(OrderItem[]) orderItems.ToArray(typeof(OrderItem));
      return target;
}

This function maps the fields from the order object recived from the mainframe through MQ (IBM)  -  Biztalke  and a webservece, to the order object used in the front end.

Several other functioions in this class maps other objects before sending and recivening to the mainframe. All this functions (or methods if you perfer) are declared as static.

Since only one instance of EntityMapper exist userA and userB will both use the same  CopyToOrderDto methode and hence UserB can get userA's data. Which makes sense to me.

So the sulution will be to remove the static from the functions and change the calling of them to instance a new object each time. Can you confirm that this is what you recomend?

I will try to get accept for trying this. And if we tries it and the error goes away, then this case is solved.



(I'm a temp working on this project while the programmer is on sick leave. No other in the company works on .NET - only on mainframe (Cobol I guess))
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Ted Bouskill

Yes, that looks like the problem.  No objects with specific customer data should be static on a web application.  I wonder if it was done as a workaround to deal with a compile issue.
Ervik

ASKER
I have a hard time try to convince my manager to try this. (He's hard to believe that code that has run fine for years, suddenly don't work correctly any more.)

Could it be that they who made the system had some sort of locking? I know I don't use one attribute that was used in the previous page. The attribute lead to a custom dll that is the property of the consulting company that has made the webshop in the first place, and we don't have source for this dll. The attribute is:
[FieldPersistence(FieldPersistenceType.Session)]
I removed it to se if there was any difference. But could not find any in testing, so this was not used in the version that produced the error.

>I wonder if it was done as a workaround to deal with a compile issue.
It could have been in an atemt to optimize it for speed. I have heard talk about a round of optimzation a few years ago. (Done by the same company.)

But using static function and som kind of locking is slower that using instances, right?
Ted Bouskill

So to be clear, by removing the attribute the error disappeared?  It might have been implemented to solve a perceived problem.

Using static functions with locking will cause performance and other problems because UserB would have to wait for UserA to unlock the record.

By the way, some errors might not show for years until the right conditions are met like load on the server.
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
Ervik

ASKER
>So to be clear, by removing the attribute the error disappeared?  It might have been >implemented to solve a perceived problem.

No, you missunderstand. There was this attribute on the page_load method on the old page, but I skiped it on the new page. And we got the error when the attribut is missing. Have not tried it with the attribut set.

But anyway, it shoud be better to use instanced methods than to use static methods and some kind of locking, to prevent contention errors?
Ted Bouskill

OK, then put that attribute back.  I'm not familiar with it but FieldPersistence(FieldPersistenceType.Session) might force the data to be per session which is what you want.

If you get rid of the static methods you don't need locking.  Without static methods each user will get their own copy of the object.  Locking is painful on web applications because UserA has to wait for UserB's locks to clear if they are trying to get a page concurrently.
Ervik

ASKER
Hi tedbilly.
I'm pretty sure that your solution is correct, but I think I have to wait to this is proven, so it has to wait until my boss dessides to put it in production again. Sorry about that.
You don't have to answeere this post. I will log in and accept your solution, when proved.
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Ervik

ASKER
So we have put it in production, on Wednesdays evening. (Static function changed to instanse functions. And instantiated when used.)

When I arrived at workt the next morning the first customer has called in, that he could see data form an other customer.

I then change the function back to static as it was before, and put in the attribute on the page
([FieldPersistence(FieldPersistenceType.Session)]) and pushed it out to producktion.  But just an hour or so, a new customer called in with the same problem.

So we  have rolled back again to the old confirmation page (Order.aspx). And are back to square one.
Ted Bouskill

What are you storing in sessions?  Is there anything static being stored in sessions?
Ervik

ASKER
If you by session mean: Session["identfier"] = whatever, we only store some ID's for current user and so on.
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
Ted Bouskill

Yes that is what I was talking about.  Are there any objects stored in the Session that have a static member?  That will cause problems.
Ervik

ASKER
No objects as far as I'm aware of. Here is the complete list of Sessions in the Order2.aspx page:

private void PunchOutLogon(string _punchOutTicketKey)

TicketManager ticketManager = new TicketManager(60, list);
Ticket ticket = ticketManager.GetTicket(_punchOutTicketKey);
Session["PunchOutTicket"] = ticket;
Session["PunchOutTicket_EmptyCart"] = "true";


Session["UserId"] = _user.UserID;
Session["ProjId"] = order.ProjectID;
Session["Error"] = ex.Message
Session["isPosted"] = "posted";
Session["Ref1"] = tbxReference1.Text.Trim();
Session["Ref2"] = tbxReference2.Text.Trim();
Session["email"] = tbxEmailAddress.Text.Trim();
Session["mobil"] = txtCusMobile.Text.Trim().Replace(" ", "");
Session["fax"] = txtFaxNo.Text.Trim().Replace(" ", "");
Session["ansattnr"] = txtEmployeeNo.Text.Trim();
Session["kundeOrdreNr"] = txtCusOrderNo.Text.Trim();
Session["kundeProjNr"] = txtCusProjectNo.Text.Trim();
Session["kundeAvd"] = txtCusDepartment.Text.Trim();
Session["kundeLager"] = txtCusWarehouse.Text.Trim();
Session["rbMailSMS"] = rbMailSMS.SelectedIndex;
Session["AddressId"] = itemId;   // itemId = int.Parse(ddAddressBook.SelectedValue);

Sessions are mostly used when saving state on the page when loading an other page (also new) that let users edit, add and delete adresses, and retrun back to where they where.

TicketManager is used for customers that have tight integration with the webshop via PunchOut. But they use a different website (different port), and no problem with that part of the program.
Ted Bouskill

OK, you are storing a Ticket object in the session.  Does that object have static methods or properties?
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Ervik

ASKER
I don't think so.
Here is the declaration and internal properties:
   public class Ticket
    {
        private string password;
        private string username;
        private string userId;
        private string browserFormPost;
        private string buyerCookie;
        private DateTime ticketCreated;
        private Guid key;
        private RequestOperation operation;
        private CXMLEnvelope data;
        private string projectId;
        public Ticket(string username, string password, RequestOperation operation, string browserFormPost, string buyerCookie, string projectId, CXMLEnvelope request, string userId)
        {
            this.password = password;
            this.username = username;
            this.browserFormPost = browserFormPost;
            this.buyerCookie = buyerCookie;
            this.operation = operation;
            this.ticketCreated = DateTime.Now;
            this.key = Guid.NewGuid();
            this.projectId = projectId;
            this.data = request;
            this.userId = userId;
        }

        private RequestOperation operation; -> this i just an enum
        private CXMLEnvelope data;                -> this is a normal public class se belove:

    [Serializable]
    [XmlRoot("cXML",IsNullable=true)] //, Namespace = "http://xml.cxml.org/schemas/cXML/1.2.016/cXML.dtd")]
    public class CXMLEnvelope
    {

There are hovever severalt other static classes in the system. But they are used for logging, and getting data from web.config and so on.
Ted Bouskill

Hmm, well other than incorrect data, the only way this error occurs is shared state on the server and that only occurs with static values.  There must be something hidden somewhere that is causing this effect.
Ervik

ASKER
We are currently investating some caching that may cause this effect.
This is the best money I have ever spent. I cannot not tell you how many times these folks have saved my bacon. I learn so much from the contributors.
rwheeler23
Ted Bouskill

The Application Cache in ASP.NET is shared with all users.  If you want data to be specific to a user, then use Sessions.
ASKER CERTIFIED SOLUTION
Ervik

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Ervik

ASKER
The sulution offered by the expert, did not help i our situation, but may be correct in other senarios.