Juanjo's Blog

Dot Net Development | Technology | Xbox freak :-)

  Home :: Contact :: Syndication  :: Login
  11 Posts :: 0 Stories :: 4 Comments :: 0 Trackbacks

Archives

Post Categories

My Blog Read List

My links

Thursday, February 02, 2006 #

In the project I'm working on, there is a ASP application that mantains the user id information in a Session variable. I had to add a new permisssions management zone to the application in ASP.Net 2.0, and I didn't want to rework again all the Login scenario (the best way to do this should be using the built-in controls in ASP.Net 2.0)... But i decided to get the ASP user id session variable to my ASP.Net application to get the user that logged in in the ASP app.

Do achieve this, I do need a simple GetSession.ASP page that helps me getting the session variable:

<%
        Option Explicit

        Dim sessionValue
        'This is an important check, disallow any remote user to get session variables, and only allows queries from the local server
        If Request.ServerVariables("REMOTE_ADDR") = Request.ServerVariables("LOCAL_ADDR") Then 
            sessionValue = Request("SessionVar")
            If trim(sessionValue) <> "" Then
              Response.Write Session(sessionValue)
            End If
        Else 
            Response.Write "Forbidden"
            Response.Status = "403"
        End If
%>

Now we can call this page (with a GET GetSession.asp?SessionVar=variable_name) from any ASP.Net code, to get the session variable. But there is a point to check... The ASPSESSION cookie you have to pass to this page, so the server can find the related session variable requested. This is a simple code you can use in your app to get the session variable you need:

        public string GetSessionVar(HttpContext oContext, string ASPSessionVar)
        {
            //Define asp page to call:
            string ASPSessionVarASP = "";
            System.Uri oURL = oContext.Request.Url;
            ASPSessionVarASP = oURL.Scheme + "://"
              + oURL.Host + ":" + oURL.Port.ToString() + "/" + oURL.AbsolutePath.Substring(0, oURL.AbsolutePath.LastIndexOf("/")) + "/"
              + "GetSession.ASP";

            // First get the Session Cookies to add to the request. This is important because if no ASPSESSION cookie is present, the 
            // server cannot retrieve the session variable value
            string[] ASPCookieName;
            string[] ASPCookieValue;
            if (!GetSessionCookie(out ASPCookieName, out ASPCookieValue))
            {
                return "";
            }

            // Initialize the WebRequest, with a QueryString parameter with the name
            HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(ASPSessionVarASP + "?SessionVar=" + ASPSessionVar);

            // Add all ASPSESSION cookies to the request
            for(int i=0; i<ASPCookieName.Length; i++)
                myRequest.Headers.Add("Cookie: " + ASPCookieName[i] + "=" + ASPCookieValue[i]);

            // Send the request and get a response
            HttpWebResponse myResponse = (HttpWebResponse)myRequest.GetResponse();
            Stream receiveStream = myResponse.GetResponseStream();
            System.Text.Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
            StreamReader readStream = new StreamReader(receiveStream, encode);

            // Get the response
            string sResponse = readStream.ReadToEnd();

            // Cleanup
            myResponse.Close();
            readStream.Close();

            return sResponse;
        }

Now we need the function that gets the ASPSESSION cookies names and values:

        private bool GetSessionCookie(out string[] ASPCookieName, out string[] ASPCookieValue)
        {
            int loop1;
            HttpCookie myCookie;     // Cookie variable

            ArrayList names = new ArrayList();
            ArrayList values = new ArrayList();

            // Capture all cookie names into a string array.
            String[] CookieArray = oContext.Request.Cookies.AllKeys;

            // Grab individual cookie objects by cookie name.
            for (loop1 = 0; loop1 < CookieArray.Length; loop1++)
            {
                myCookie = oContext.Request.Cookies[CookieArray[loop1]];
                if (myCookie.Name.StartsWith("ASPSESSION"))
                {
                    names.Add(myCookie.Name);
                    values.Add(myCookie.Value);
                }
            }

            // Return the values
            ASPCookieName = (string[])names.ToArray(typeof(string));
            ASPCookieValue = (string[])values.ToArray(typeof(string));

            // return true if any cookie found
            return (names.Count > 0);
        }


Now, in the ASP.Net page you need the legacy session variable, you have to call something like this:


                string userid = aspSession.GetSessionVar(this.Context, "userId");

Hope this works for you as it did for me :-)

posted @ 1:21 AM

Monday, September 12, 2005 #

Hi guys!

After a few weeks of holidays, a week in Tenerife, some days in Menorca, and a week also in Portugal (Lisboa and Algarve), now I've charged my batteries and I'm back to kick some butts... Ok, maybe I'm not going to kick anybody, but I'm going to write some posts here and there...

I left the project where i was for the last year, and for now I will stay in ilitia's offices doing some internal projects with Visual Studio 2005 and SQL Server 2005... To start, I need to check what's new in these new versions, so I'm going to read the free online courses that Microsoft provides...

https://www.microsoftelearning.com/visualstudio2005/

See you very soon.

posted @ 7:56 PM

Saturday, May 28, 2005 #

In the project currently I am working, I am migrating a legacy BizTalk 2002 application to BizTalk 2004. As you probably already know, the migration path between the two products is far from easy... So I am rewriting all from scratch so I can take all advantadges that .Net provides, and avoiding the legacy limitations from COM world...

In the current post, I will talk about Custom Pipeline Components. If you know already BTS 2002, the Pipeline Components in BTS 2004 are similar from the Application Integration Components (AIC) from BTS 2000 / 2002. And I am working in a Custom Pipeline Component for transforming an XML with a propietary (and very huge) XSL to convert this XML to a MIME document. Also, this Pipeline Component is reading the MIME response from the remote service and extracting the embedded XML document.

The Custom Pipeline inherits from some interfaces, and one of this, IComponent, exposes a public method named Execute. This method is executed every time the Custom Pipeline Component is called from a Pipeline.

And in this step was where my troubles arised... I had this code, in the Execute method, that was transforming the MIME into an XML string:



  public IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg)
  {
   IBaseMessagePart bodyPart = inmsg.BodyPart;
   Stream originalStrm = null;
   MemoryStream strm = new MemoryStream();

   try
   {   
    if (bodyPart!=null)
    {
     // Get a *copy* of the original input stream
     originalStrm = bodyPart.Data;
     if (originalStrm != null)
     {
      //Read Incoming data
      string data = "";

      StreamReader sreader = new StreamReader(originalStrm, System.Text.Encoding.UTF8);

      //Receive pipeline, parse MIME document and extract XML
      data = this.fromMIME( sreader.ReadToEnd() );     

      //Send the data back to the Message
      StreamWriter swriter = new StreamWriter(strm, System.Text.Encoding.UTF8);
      swriter.Write(data);
      swriter.Flush();
      strm.Seek(0, System.IO.SeekOrigin.Begin);

     }
    }
   }
   catch (Exception ex)
   {
    System.Diagnostics.EventLog.WriteEntry(ex.Source, ex.Message + "\n" + ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
    strm = (MemoryStream) originalStrm;
   }
   finally
   {
    bodyPart.Data = strm;
    pc.ResourceTracker.AddResource( strm );
   }
            
   return inmsg;
  }

This code was working perfect for me... Until I connect it to my Receive Pipeline and to my Orchestration. When unit testing the orchestration, all messages were suspended, with an exception saying that the message, with an empty namespace, was not corresponding with the expected one, "www.clearscreen.com#Response". It was very disssapointing, because the XML was in a proper format and with it expected namespace in place, the root tag was "Response" and its namespace was "www.clearscreen.com" :

But this was not enough for BizTalk to route the message. I discovered that we need to promote a property of the message in the Custom Pipeline:



  public IBaseMessage Execute(IPipelineContext pc, IBaseMessage inmsg)
  {
   IBaseMessagePart bodyPart = inmsg.BodyPart;
   Stream originalStrm = null;
   MemoryStream strm = new MemoryStream();

   try
   {   
    if (bodyPart!=null)
    {
     // Get a *copy* of the original input stream
     originalStrm = bodyPart.Data;
     if (originalStrm != null)
     {
      //Read Incoming data
      string data = "";

      StreamReader sreader = new StreamReader(originalStrm, System.Text.Encoding.UTF8);

      //Receive pipeline, parse MIME document and extract XML
      data = this.fromMIME( sreader.ReadToEnd() );     


      //Send the data back to the Message
      StreamWriter swriter = new StreamWriter(strm, System.Text.Encoding.UTF8);
      swriter.Write(data);
      swriter.Flush();
      strm.Seek(0, System.IO.SeekOrigin.Begin);

      // IMPORTANT CODE HERE: Promote the message type context property
      string systemPropertiesNamespace = "http://schemas.microsoft.com/BizTalk/2003/system-properties";
      string messageType = "www.clearscreen.com#Response"; 
      inmsg.Context.Promote("MessageType", systemPropertiesNamespace, messageType);

     }
    }
   }
   catch (Exception ex)
   {
    System.Diagnostics.EventLog.WriteEntry(ex.Source, ex.Message + "\n" + ex.StackTrace, System.Diagnostics.EventLogEntryType.Error);
    strm = (MemoryStream) originalStrm;
   }
   finally
   {
    bodyPart.Data = strm;
    pc.ResourceTracker.AddResource( strm );
   }
            
   return inmsg;
  }

Hope this helps!

posted @ 5:12 PM

Tuesday, April 26, 2005 #

Wow... Two posts in a day! Just incredible for me!!! (LOL, this is for Miguel that is always bugging me to post) :o)

As I told in the previous post, I am having difficulties when serializing to Xml with DateTime and Boolean types, because they are serialized in a format I don´t need. For example, DateTime types serialize like 2005-01-23T00:01:02.000000+02:00 (with millisecs an time zone info). I do not need this. I have workarounded this in the following way:

When you run XSD.exe with a schema, it gives you a class (or a collection of them). In each class you can find this method (for a DateTime class):

 
  ///Original method
  [System.Xml.Serialization.XmlElementAttribute(Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  public System.DateTime DateDistributed 
  {
   get 
   {
    return this.dateDistributedField;
   }
   set 
   {
    this.dateDistributedField = value;
   }
  }

If you change the property to this, you can control the format the DateTime is serialized with.

 
  /// 
  /// This is the new method, I've decorated it with XmlElementAttribute attribute and the name of the original Property.
  /// The DateTime is serialized as a String, and you can control the output format for the date / time.
  /// 
  [System.Xml.Serialization.XmlElementAttribute("DateDistributed", Form=System.Xml.Schema.XmlSchemaForm.Unqualified)]
  [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
  public string __DateTime_DateDistributed
  {
   get
   {
    if (this.dateDistributedField != System.DateTime.MinValue)
     return this.dateDistributedField.ToString("yyyy-MM-ddTHH:mm:ss");
    else 
     return System.String.Empty;
   }
   set
   {
    this.dateDistributedField = System.DateTime.Parse(value);
   }
  }

  /// 
  /// This is the old method, I've decorated it with XmlIgnore attribute. This makes the original property not serializing.
  /// 
  [System.Xml.Serialization.XmlIgnore()]
  public System.DateTime DateDistributed 
  {
   get 
   {
    return this.dateDistributedField;
   }
   set 
   {
    this.dateDistributedField = value;
   }
  }

Yes, I know this is not the best solution if you have a large schema (like mine), but at least I can control how I output my values to Xml.

The best solution would be change the XmlSerializer do the serialization of the types, but I didn't find out how to do it... If you know please let me know!

 

posted @ 4:56 PM

In the project I'm currently working on, I needed to create a XML from a pretty complex XSD Schema. This schema is very complex because has a lot of imports and includes. The logical way to create a Xml from the XSD is running the XSD.EXE tool (that tool is included in Visual Studio 2003) to generate a class hierarchy, and then, after including this generated classes in the project, populate this classes and serialize them to Xml with the XmlSerializer object.

Here comes the problem: XSD.EXE always returned me the error "Specified cast is not valid". After a few research, I had seen that XSD.EXE was not able to support some sympleTypes and also the "xsd:include schemaLocation" in a proper way. I've tryed some other tools with no luck, XSDObjectGen or CodeXS also failed to generate for me an object that I can use to generate my Xml.

The solution for me was a bit strange, but successful anyway... I tryed to generate the object with an installation of Visual Studio 2005 beta that I have in a virtual machine. I ran the XSD.EXE tool with the schema, and in the first try, the tool generated the C# classes properly. I was surprised, but tryed to import the .cs file into my Visual Studio 2003 project. After removing some duplicated values in an enumerated type, it was compiling successfully... And it works very fine!

Now the trouble I have is the DateTime and Boolean types are non serializing like I need, boolean values are serializing with it's literal value 'true' - 'false' instead of '1' - '0', and the DateTime values are serializing in ISO format, but with the time zone, and I don't need this... But this will be for another article!

posted @ 11:47 AM