Thursday 20 August 2009

Silverlight Application – Access to Server side variables

The question was asked in the Silvelright.net forum how can the Silverlight application get the user IP address. One of the ways this can be done trough the Silverlight initParams.

Here is a working example that gives the application copy of the REMOTE_ADDR and HTTP_USER_AGNET proeprties from the Request.ServerVariables on the server.

To pass parameters to the Silverlight application a new parameter with name initialParams need to be added to the object that hosts the application:

<param name="initParams" value='ip=<%=(Request.ServerVariables["REMOTE_ADDR"])%>,agent=<%=(Request.ServerVariables["HTTP_USER_AGENT"])%>' />



Practically any parameter can be made available. Each parameter is passed as “key”=”value” pair and the parameters are separated by a comma (“,”). The only issue that needs to be handled is when the data contains a comma – then it needs to be escaped.



Here is a working example code (testpage.aspx):



<%@ Page Language="C#" AutoEventWireup="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<
html xmlns="http://www.w3.org/1999/xhtml" >
<
head runat="server">
<
title>silverlight.net</title>
<
style type="text/css">
html, body {
height: 100%;
overflow: auto;
}
body {
padding: 0;
margin: 0;
}
#silverlightControlHost {
height: 100%;
text-align:center;
}
</style>
<
script type="text/javascript" src="Silverlight.js"></script>
<
script type="text/javascript">
function
onSilverlightError(sender, args) {
var appSource = "";
if (sender != null && sender != 0) {
appSource = sender.getHost().Source;
}

var errorType = args.ErrorType;
var iErrorCode = args.ErrorCode;

if (errorType == "ImageError" || errorType == "MediaError") {
return;
}

var errMsg = "Unhandled Error in Silverlight Application " + appSource + "\n" ;

errMsg += "Code: "+ iErrorCode + " \n";
errMsg += "Category: " + errorType + " \n";
errMsg += "Message: " + args.ErrorMessage + " \n";

if (errorType == "ParserError") {
errMsg += "File: " + args.xamlFile + " \n";
errMsg += "Line: " + args.lineNumber + " \n";
errMsg += "Position: " + args.charPosition + " \n";
}
else if (errorType == "RuntimeError") {
if (args.lineNumber != 0) {
errMsg += "Line: " + args.lineNumber + " \n";
errMsg += "Position: " + args.charPosition + " \n";
}
errMsg += "MethodName: " + args.methodName + " \n";
}

throw new Error(errMsg);
}
</script>
</
head>
<
body>
<
form id="form1" runat="server" style="height:100%">
<
div id="silverlightControlHost">
<
object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">
<
param name="source" value="ClientBin/silverlight.net.xap"/>
<
param name="onError" value="onSilverlightError" />
<
param name="background" value="white" />
<
param name="minRuntimeVersion" value="3.0.40624.0" />
<
param name="autoUpgrade" value="true" />
<
param name="initParams" value='ip=<%=(Request.ServerVariables["REMOTE_ADDR"])%>,agent=<%=(Request.ServerVariables["HTTP_USER_AGENT"])%>' />
<
a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">
<
img src="http://go.microsoft.com/fwlink/?LinkId=108181" alt="Get Microsoft Silverlight" style="border-style:none"/>
</
a>
</
object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>
</
form>
</
body>
</
html>



Here is the Silverlight Application code (App.xaml.cs) :



using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace silverlight.net
{
public partial class App : Application
{

public App()
{
this.Startup += this.Application_Startup;
this.Exit += this.Application_Exit;
this.UnhandledException += this.Application_UnhandledException;

InitializeComponent();
}

private void Application_Startup(object sender, StartupEventArgs e)
{
if(e.InitParams != null)
{
foreach(var item in e.InitParams)
{
this.Resources.Add(item.Key, item.Value);
}
}

this.RootVisual = new UserIPAddress();
}

private void Application_Exit(object sender, EventArgs e)
{

}
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
// If the app is running outside of the debugger then report the exception using
// the browser's exception mechanism. On IE this will display it a yellow alert
// icon in the status bar and Firefox will display a script error.
if (!System.Diagnostics.Debugger.IsAttached)
{

// NOTE: This will allow the application to continue running after an exception has been thrown
// but not handled.
// For production applications this error handling should be replaced with something that will
// report the error to the website and stop the application.
e.Handled = true;
Deployment.Current.Dispatcher.BeginInvoke(delegate { ReportErrorToDOM(e); });
}
}
private void ReportErrorToDOM(ApplicationUnhandledExceptionEventArgs e)
{
try
{
string errorMsg = e.ExceptionObject.Message + e.ExceptionObject.StackTrace;
errorMsg = errorMsg.Replace('"', '\'').Replace("\r\n", @"\n");

System.Windows.Browser.HtmlPage.Window.Eval("throw new Error(\"Unhandled Error in Silverlight Application " + errorMsg + "\");");
}
catch (Exception)
{
}
}
}
}



Here is the Page XAML (UserIPAddress.xaml):



<navigation:Page x:Class="silverlight.net.UserIPAddress" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
xmlns:navigation="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Navigation"
d:DesignWidth="640" d:DesignHeight="480"
Title="UserIPAddress Page">
<
Grid x:Name="LayoutRoot">
<
StackPanel>
<
TextBlock x:Name="IpAddress"></TextBlock>
<
TextBlock x:Name="UserAgent"></TextBlock>
</
StackPanel>
</
Grid>
</
navigation:Page>



Here is the Silverlight Page codebehind  (UserIPAddress.xaml.cs):



using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Navigation;

namespace silverlight.net
{
public partial class UserIPAddress : Page
{
public System.String ClinetIP;
public UserIPAddress()
{
InitializeComponent();

if (App.Current.Resources.Contains("ip"))
IpAddress.Text = (System.String)App.Current.Resources["ip"];

if (App.Current.Resources.Contains("agent"))
UserAgent.Text = (System.String)App.Current.Resources["agent"];
}
}
}



I hope this helps!



Tzanimir

No comments: