IValueConverter in
the Silverlight and Wpf are same.Refer my previous post here.
Saturday, 31 March 2012
Tuesday, 20 March 2012
Windows Azure Instance To Instance Communication
If you set Instance count value in configuration for
webrole/workerrole your application will run on two instances.The loadbalancer
in azure uses some techniques to direct requests to instances.To communicate
instance to instance we have to use internal endpoints.
->Create new azure project and add new workerrole
project.
->Open ServiceDefinition.csdef file add new endpoints for wcf service and for
internal communication.
<Endpoints>
<InputEndpoint name="Rest" protocol="http" port="80" />
<InternalEndpoint name="InternalRest" protocol="tcp" />
</Endpoints>
->Add new IService interface.
Service
Interface:
[ServiceContract]
public interface
IService
{
[OperationContract]
[WebGet]
string SayHello(string
name);
}
-> Add new IWorker interface.
[ServiceContract]
public interface
IWorker
{
[OperationContract]
void UpdateMessage(string message, string
roleId);
}
->Add new Service class and
implement IService, IWorker interfaces.
Service
Implementation:
[AspNetCompatibilityRequirements(RequirementsMode
= AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(IncludeExceptionDetailInFaults
= true, InstanceContextMode = InstanceContextMode.Single)]
public class
Service : IService,
IWorker
{
//Static Message variable.
public static
string Message = "";
public string
SayHello(string message)
{
//Set the
message.
Message = message;
//Get the
role id.
string
roleId = RoleEnvironment.CurrentRoleInstance.Id;
//Notify
all instances.
WorkerRole.NotifyAllNodes(message);
return
"Hello" + message;
}
//Update the message.
public void
UpdateMessage(string message, string roleId)
{
//Set the
message.
Message = message;
}
}
->Open WorkerRole.cs
class,create serviceHost varaible
and add CreateServiceHost method to host our
Wcf REST service.
//Static channel factory
for inter-role communication.
private static ChannelFactory<IWorker> factory;
private ServiceHost serviceHost;
private void CreateServiceHost()
{
//Url of service.
Uri httpUri = new Uri(String.Format("http://{0}/{1}",
RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Rest"].IPEndpoint.ToString(), "Rest"));
//Assign url to service host.
serviceHost = new ServiceHost(typeof(Service), httpUri);
//Adding endpoint for REST service.
ServiceEndpoint ep =
serviceHost.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
//Adding behavior
for REST service.
ep.Behaviors.Add(new
WebHttpBehavior() { HelpEnabled = true });
//NetTcpBinding with
no security.
NetTcpBinding
binding = new NetTcpBinding(SecurityMode.None);
//Define an internal
endpoint for inter-role traffic.
RoleInstanceEndpoint internalEndPoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["InternalRest"];
//Add internal endpoint.
this.serviceHost.AddServiceEndpoint(typeof(IWorker),
binding, String.Format("net.tcp://{0}/InternalRest",
internalEndPoint.IPEndpoint));
//Create channel factory
for inter-role communication.
WorkerRole.factory = new ChannelFactory<IWorker>(binding);
//Open the service
host to start listening for messages.
serviceHost.Open();
}
->Create NotifiyAllNodes function
to notify the instances.
internal static void NotifyAllNodes(string
message)
{
//Get the
role id.
string
roleId = RoleEnvironment.CurrentRoleInstance.Id;
//Gets
a RoleInstance object representing the role instance in which this code is
currently executing.
var
current = RoleEnvironment.CurrentRoleInstance;
//Get
all instances except the current.
var
endPoints = current.Role.Instances
.Where(instance
=> instance != current)
.Select(instance => instance.InstanceEndpoints["InternalRest"]);
foreach
(var ep in
endPoints)
{
//Internal
endpoint address.
EndpointAddress
address = new EndpointAddress(String.Format("net.tcp://{0}/InternalRest",
ep.IPEndpoint));
//Channel
for communication.
IWorker
client = WorkerRole.factory.CreateChannel(address);
//Update
all the instances.
client.UpdateMessage(message, ep.RoleInstance.Id);
}
}
->Call CreateServiceHost function
in OnStart() method.
If you follow all these steps and upload it then you got
error like below.
HTTP could not register URL
http://+:80/Rest/. Your process does not have access rights to this namespace
(see http://go.microsoft.com/fwlink/?LinkId=70353 for details). Source:System.ServiceModel.
Solution to this problem is find out the port it needs to
open and give the workerrole permission to open the appropriate port.
->Create new console project PortDetect
and configure Target framework as 3.5.
->Open Program.cs file and add below
code which is used to detect the port and assign permission to open the
appropriate port.
class Program
{
static void
Main(string[] args)
{
Process.Start("netsh", string.Format("http add urlacl url=http://+:{0}/Service user=everyone
listen=yes delegate=yes",
RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Rest"].IPEndpoint.Port.ToString()));
}
}
->Build the
project and get the executable into you
workerrole project.
->Set the Copy to Output Directory property of executable to Copy Always.
-> Open ServiceDefinition.csdef file specify PortDetect.exe
as a startup task.
<Startup>
<Task commandLine="PortDetect.exe" executionContext="elevated" taskType="simple">
</Task>
</Startup>
Now you can access the
RestService which is hosted(at port 80)
on workerrole.And you can do instance to instance communication.
You can’t understand what instance
is updating the Message
variable here.You can use blob storage to get these details.Write the
data(roleId) to the blob storage in the SayHello and UpdateMessage functions.
Let me know, if you have any feedback. Mail me for source code. Enjoy
reading my articles…
sekhartechblog@gmail.com
LongPolling
In Ajax
technique client send the request to the web server and server responds to the
client with Json/xml data.
Where in
longpolling the request is kept alive at the server and gives the response when
data exists.After receiving the request client should make another request for
further updates.
In .Net there is IHttpAsyncHandler
which is mainly used for longpolling implementation.
->Create
a Handler class and
inherit it from IHttpAsyncHandler.
public class Handler : IHttpAsyncHandler
{
//Static varible of StateManager.
private static StateManager stateManager;
//Constructor.
static Handler()
{
//Intilizing object.
stateManager = new StateManager();
}
//StateManager.
public static StateManager StateManager
{
get { return stateManager; }
}
//Initiates an asynchronous call to the HTTP handler.
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, objectextraData)
{
//Calling the ProcessRequest.
return stateManager.ProcessRequest(context, cb, extraData);
}
// Provides an asynchronous process End method when the process ends.
public void EndProcessRequest(IAsyncResult result)
{
}
//Gets a value indicating whether another request can use the
System.Web.IHttpHandler instance.
public bool IsReusable
{
get { return false; }
}
//Enables processing of HTTP Web requests by a custom HttpHandler that
implements the System.Web.IHttpHandler interface.
public void ProcessRequest(HttpContext context)
{
}
}
->Create the StateManager class.
public
class StateManager
{
//List of clients.
List<AsyncRequestState>
lstClients = new List<AsyncRequestState>();
public IAsyncResult
ProcessRequest(HttpContext context, AsyncCallback cb, object
extraData)
{
//Get the
date value from querystring.
string
date = context.Request["date"];
//Creating
AsyncRequestState object.
AsyncRequestState
requestState = new AsyncRequestState(context,
cb, extraData);
//Adding new client.
lstClients.Add(requestState);
//Return
IAsyncResult.
return
requestState;
}
//Send message to all clients.
public void
SendMessage(string message)
{
//Send
message to all clients.
foreach
(AsyncRequestState item in lstClients)
{
//Check
the status of operation
if
(item.IsCompleted == true)
{
}
else
{
//Write
the message to response.
item.context.Response.Write("<b>Updates
from Servce:</b> " +
message);
//Flush
the message to user.
item.context.Response.Flush();
//Complete
the request.
item.CompleteRequest();
}
}
//Clear
the client list.
lstClients.Clear();
}
}
->Create the AsyncRequestState
class and inherit it from IAsyncResult.
//Inherit a class from IAsyncResult which
Represents the status of an asynchronous operation.
public class
AsyncRequestState : IAsyncResult
{
//Constructor.
public AsyncRequestState(HttpContext con, AsyncCallback
cb, object extraData)
{
//Httpcontext.
this.context
= con;
//Callback.
this.cb
= cb;
//Extradata.
this.extraData
= extraData;
}
public HttpContext
context;
public string
clientName;
private AsyncCallback
cb;
private object
extraData;
private bool
isCompleted = false;
internal void
CompleteRequest()
{
isCompleted = true;
if
(this.cb != null)
this.cb(this);
}
#region InterfaceImplementation
public object
AsyncState
{
get
{
return
(this.extraData);
}
}
public WaitHandle
AsyncWaitHandle
{
get
{
return
null;
}
}
public bool
CompletedSynchronously
{
get
{
return
(false);
}
}
public bool
IsCompleted
{
get
{
return
(isCompleted);
}
}
#endregion
}
->Register the Handler in Web.config
file under System.web configuration.
<httpHandlers>
<add verb="POST" path="Handler.ashx" type="LongPolling.Handler, LongPolling"/>
</httpHandlers>
If you publish in IIS you should add this configuration under System.webserver
configuration.
<handlers>
<add name="Handler" verb="POST" path="Handler.ashx" type="CricgambleLongPolling.Handler, CricgambleLongPolling"/>
</handlers>
->Create a login.html page which is
used to polling the server.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script
src="Scripts/jquery-latest.js"
type="text/javascript"></script>
</head>
<body>
<div>
Click the button to get updates.
<input
type="button"
value="GetUpdates"
onclick="hook();"
/></div>
<div
id="updates">
</div>
</body>
<script type="text/javascript">
//Hook the request.
function hook() {
//Url of the service.
var url = 'Handler.ashx?date='
+ new Date();
//Jquery ajax function to call the
service.
$.ajax({
type: 'POST',
//Method type.
url: url, //Url of
handler.
beforeSend: function (xhr) {
//Here
we have to pass the Content-Type header to get the date value(Which is passed
in the query string).
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
},
error: function
(err) {
//Error
event.
alert('error
occured');
},
success: function
(res) {
//Display
the updates.
$("#updates").append($("<div/>").html(res));
//Hook
the request after a successfull response.
hook();
}
});
}
</script>
</html>
->Create a wcf service which is
used to send data to the handler.
namespace LongPolling
{
[ServiceContract]
public interface
IService
{
[OperationContract]
void SendMessage(string message);
}
}
namespace LongPolling
{
public class
Service : IService
{
public void
SendMessage(string message)
{
//Calling
the SendMessage method to send updates.
Handler.StateManager.SendMessage(message);
}
}
}
->Add service reference to the wcf
service.
->Create SendMessage.aspx page.
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form
id="form1"
runat="server">
<div>
Enter Message.
<asp:TextBox ID="txtMessage"
runat="server"></asp:TextBox>
</div>
<div>
<asp:Button ID="btnSend"
runat="server"
Text="SendMessage"
onclick="btnSend_Click" /></div>
</form>
</body>
</html>
->In code behind.
namespace LongPolling
{
public partial
class SendMessage
: System.Web.UI.Page
{
//Create client object.
ServiceReference.ServiceClient
objClient = new ServiceReference.ServiceClient();
protected void
Page_Load(object sender, EventArgs e)
{
}
protected void
btnSend_Click(object sender, EventArgs e)
{
if
(txtMessage.Text != "")
{
//Calling
the service function.
objClient.SendMessage(txtMessage.Text.ToString());
}
}
}
}
Now run the application open the
login.html page and click on GetUpdates button.Open SendMessage.aspx in the new
browser window enter some text and click on SendMessage button which will
update all the clients.
In long polling different browsers have
different bahaviors.You should write code based on the browser.
If you have multiple clients you
should implement some threading concepts in the server side,then you can’t miss the single piece of data.
Let me know, if you have any feedback. Mail me for source code. Enjoy reading my articles…
sekhartechblog@gmail.com
Subscribe to:
Posts (Atom)

