Search code examples
c#asp.netxmlweb-servicesasmx

Error consuming Web Service ASP.NET


So, I'm studying Web Services in ASP.NET and I have a question. I have two methods: Add (that does the sum of two numbers) and GetCalculations (that displays the latest calculations, through EnabledSession property). When I open my .asmx on browser, it shows the sum and the latest calculations in a xml file, but, when I open my Web Form on browser, I can do the sum, but the calculations are not displayed.

This is my codes:

WebForm1.aspx.cs

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

namespace CalculatorWebApplication
{
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        protected void btnAdd_Click(object sender, EventArgs e)
        {
            CalculatorService.CalculatorWebServiceSoap client =
                new CalculatorService.CalculatorWebServiceSoapClient();
            int result = client.Add(Convert.ToInt32(txtFirstNumber.Text),
                Convert.ToInt32(txtSecondNumber.Text));
            lblResult.Text = result.ToString();

            gvCalculations.DataSource = client.GetCalculations();
            gvCalculations.DataBind();

            gvCalculations.HeaderRow.Cells[0].Text = "Recent Calculations";
        }
    }
}

WebForm1.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="CalculatorWebApplication.WebForm1" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <table style="font-family:Arial">
        <tr>
            <td>
                <b>First Number</b>
            </td>
            <td>
                <asp:TextBox ID="txtFirstNumber" runat="server"></asp:TextBox>
            </td>
        </tr>
        <tr>
            <td>
                <b>Second Number</b>
            </td>
            <td>
                <asp:TextBox ID="txtSecondNumber" runat="server"></asp:TextBox>
            </td>
        </tr>
        <tr>
            <td>
                <b>Result</b>
            </td>
            <td>
                <asp:Label ID="lblResult" runat="server"></asp:Label>
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <asp:Button ID="btnAdd" runat="server" Text="Add" OnClick="btnAdd_Click" />
            </td>
        </tr>
        <tr>
            <td colspan="2">
                <asp:GridView ID="gvCalculations" runat="server">

                </asp:GridView>
            </td>
        </tr>
    </table>
    </form>
</body>
</html>

CalculatorWebService.asmx.cs

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

namespace WebServicesDemo
{
    /// <summary>
    /// Summary description for CalculatorWebService
    /// </summary>
    [WebService(Namespace = "http://pragimtech.com/webservices")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class CalculatorWebService : System.Web.Services.WebService
    {

        [WebMethod(EnableSession = true)]
        public int Add(int firstNumber, int secondNumber)
        {
            List<string> calculations;
            if (Session["CALCULATIONS"] == null)
            {
                calculations = new List<string>();
            }
            else
            {
                calculations = (List<string>)Session["CALCULATIONS"];
            }

            string strRecentCalculation = firstNumber.ToString() + " + " 
                + secondNumber.ToString() + " = " 
                + (firstNumber + secondNumber).ToString();
            calculations.Add(strRecentCalculation);
            Session["CALCULATIONS"] = calculations;

            return firstNumber + secondNumber;
        }

        [WebMethod(EnableSession = true)]
        public List<string> GetCalculations()
        {
            if (Session["CALCULATIONS"] == null)
            {
                List<string> calculations = new List<string>();
                calculations.Add("You have not performed any calculations");
                return calculations;
            }
            else
            {
                return (List<string>)Session["CALCULATIONS"];
            }
        }
    }
}

Solution

  • On the server side: With the EnabledSession attribute on the web service, the web service will main session state and keeps the previous calculations around in Session state for the same client. How does the web service know it's the same client? Cookie.

    When you are using a browser, cookie will be used and stored in your browser. This allows the web service to identify the client. Result: you see previous calculations in the response xml.

    When you are calling it from webform, you need additional step so that cookies will be used. For asmx web service client (if you add WebReference), it will be something like:

    client.CookieContainer = new CookieContainer
    

    For wcf service client (if you add ServiceReference), you can enable cookie from the configuration:

    <system.ServiceModel>
        <bindings>
            <basicHttpBinding allowCookies="true">
        </bindings>
    ......
    </system.ServiceModel>