Showing posts with label AppFabric. Show all posts
Showing posts with label AppFabric. Show all posts

Reading Notes # 72

http://www.sxc.hu/photo/1358858Cloud
Integration
  • AppFabric - Frequently Asked Development Questions (Ed Price - MSFT Ed Price - MSFT Microsoft MSFT 122,146 Points 25 20 17 Recent Achievements Proposed Answerer III Gallery Contributor II Wiki Ninja View Profile) - Good questions... with their answers.
Programming
Miscellaneous

~Frank





Reading Notes #46


 

Cloud

 

Programming

“there is, as Joshua Topolsky puts it, “a missing link in our computing experience” (engt.co/9GVeKl). “
  • The key to AddOrUpdate (Arthur Vickers) - While waiting for the next release of EF this post explain very clearly how to implement an extension method to help use in a more generic context when we want the same functionality of the DbSet.Find in a AddUpdateEntity method.
  • Mocking Dependencies != IoC (or at least it doesn’t have to) (Vincent-Philippe Lauzon) - Interesting tutorial that explains an alternative to mock without using dependency injection IoC by using the Lazy.
 

Integration

  • Michael Stephenson - Tips on when not using BizTalk config file and reference on another post to more details.
"I wrote a blog post a few years ago around the options for where you could put configuration settings in BizTalk (Click here)."
 

Miscellaneous


~Frank


Reading Notes #44

They Will Bring You In The Cloud
They will bring you in the cloud.

Cloud


Programming

  • Code First model builder versions (Arthur Vickers) - This post explain how to configure EF code first to avoid any breaking code when updating the framework to a newer version. Nice work.
  • Créer son propre Gem et le publier - Very nice tutorial (in French) that explain in detail with a simple case how to create and also publish a Ruby Gem.

Miscellaneous

  • 5 Tricks for a Killer Company Blog - Five simple tips to get started blogging in a business perspective.
  • Hit the Presentation Sweet Spot - Twenty minutes is very short. Maybe it is a good idea for a specific type of presentation... How do you plan a 2-3 formation?
  • Your Personal Brand as a Developer: Implementing (Part 2 of 2) (Jonathan Rozenblit) - Part 2 on an unusual topic but important. Our brand, as a person. On the internet everything is amplified and could be seen by a lot of people very quickly. A post to read "before it is too late".
  • Coping with Email Overload (Peter) - This could be a good advice for a lot of people. While I'm working on a project where co-workers are across the country I not sure I can do this but maybe tweaking it with rules for only those people.

Reading Notes #36



Cloud


Programming


Miscellaneous



~ Frank



Reading Notes #32



Cloud

Let The Clouds Make Your Life Easier - Geek and poke

Programming

Miscellaneous


~Franky


Reading Notes #31





Cloud


Programming


Miscellaneous



~Franky



Reading Notes #30



Cloud


Programming

Miscellaneous

“[…] A popular saying goes that Programmers are machines that turn caffeine into code. […]”
  • Lowering Higher Education - In this post David S Platt share is idea of what could be the future of Education.... And I like this!
  • “[…] Stanford University announced that its class on artificial intelligence will be available for free online […]”
  • Agile Results for Time Management - This post present a summary of the method call Agile Result. A good way to improve your time management.
  • 500! (Richard Ziade) - If you don't know Readability take few second you should be charmed.
  • Missing Key to Unification (safeerm) - According to this post 2012 will by important in the unification processes.


~Franky

Reading Notes #29



Cloud


The biggest missing link here, is the extensibility with custom components.  At this moment, it doesn’t look possible to have (de)batching, custom validation, zipping and all these other things we do in BizTalk pipeline components.

Programming


Miscellaneous


~Franky

Reading Notes #26

 

This is the last post of 2011. Happy Holidays to every one and see you next year for others Reading Notes!


Cloud


Programming


Miscellaneous


~Franky


Reading Notes #24


Cloud



Programming

 

Miscellaneous


~Franky

Messaging with queue in Azure Service being RESTful


I was re-doing some of the labs in the Windows Azure Platform Training Kit (WAPTK) when one of then didn't works: MessagingWithQueue. A got this error message:

Could not connect to net.tcp://xxxx.servicebus.windows.net:9354/. 
The connection attempt lasted for a time span of 00:00:00.0615234. 
TCP error code 10061: No connection could be made because the target machine actively refused it.

Quickly this message is saying that the port 9354 need to be open.  So I was going to ask to open this port, but then I ask my self: “What if I couldn't?” Does Azure service Bus suppose to be super flexible and give me the opportunity to you all kind of connection? Of course it does, so I decide to make a RESTful version of this lab.

Let’s begin

Create a new Cloud project in Visual Studio, and add a web role. In fact, regular web project will work just fine, but to keep it close to the original lab I will start with a cloud on. In the content folder add preloader.gif and override the Site.css (all the code, images and files are available here). In the View / Shared folder override the Site.Master and in View / Home override Index.aspx.  You can run now the application, you should see something like that:

WebPage

Create Azure AppFabric Service Bus

On the Azure management portal at windows.azure.com In the Service Bus section, create a new Service Bus.  You will need the Service Gateway, the Default Issuer (always “owner” in the CTP) and the Default Key.

Create New Queues

To Create a queue the button “Create” in section B will send the text, the queue name, to the Home controller and let us know the result.  To do that let’s add some JavaScript /JQuery code in the Index page.
var getQueuesUrl = '< %= Url.Action("Queues") % >';

$(document).ready(function () {
    loadQueues();
    
    $("#createQueue").submit(function (event) {
        event.preventDefault();
        var url = $(this).attr('action');
        var queueName = $("#queueName").val();
        $(".loading").show();
        $("#send").attr("disabled", "true");
        $("#retrieve").attr("disabled", "true");
        $.post(url, { queueName: queueName })
            .success(function (response) { renderCreateQueueStatus(response); })
            .error(function () { renderCreateQueueStatus(false); });
    });
});

function renderCreateQueueStatus(response) {
    if (response) {
        $("#createQueueStatus").html("Queue created successfully!");
        loadQueues();
    } else {
        $("#createQueueStatus").html("An error occurred, please try again later.");
    }
    $(".loading").hide();
    $("#send").attr("disabled", "");
    $("#retrieve").attr("disabled", "");
}

function loadQueues() {
    $.get(getQueuesUrl).success(function (response) {
        var ul = $("fieldset.center > ul");
        var sendMsgCombo = $("#sendMessageQueue");
        var receiveMsgCombo = $("#retrieveMessageQueue");

        sendMsgCombo.children().remove();
        receiveMsgCombo.children().remove();
        ul.children().remove();

        for (var i = 0; i < response.length; i++) {
            var item = response[i];
            sendMsgCombo.append('<option value="' + item.Name + '">' + item.Name + '</option>');
            receiveMsgCombo.append('<option value="' + item.Name + '">' + item.Name + '</option>');
            ul.append('<li><label>' + item.Name + '</label><div class="msgCountOf' + item.Name.replace(/ /g, '') + '" style="float:right"><label>Messages</label></div></li>');
            updateMessageCountOf(item.Name, item.Messages);
        }
    });

    $(".loading").hide();
}

function updateMessageCountOf(queueName, numberOfMessages) {
 var message = numberOfMessages + " Messages";
 if (numberOfMessages == "0") message = "No Messages";
 if (numberOfMessages == "1") message = numberOfMessages + " Message";
 $("div.msgCountOf" + queueName.replace(/ /g, '') + " > label").html(message);
}
  

Once the document is ready loadQueues() is called.  This function will loop through a list of queues name and fill the two listbox  and the build the middle list .

Using Jquery the $("#createQueue") add a submit function to the button with the ID createQueue and on the success or error will call the function renderCreateQueueStatus to update the content of the Label createQueueStatus.  Then recall loadQueues() so it can refresh the queues lists.

On the server side now we will need a function CreateQueue that accept a string parameter as queue name and return a JsonResult.  This function should act as a HttpPost. To communicate a token is needed.  This is done by the primary call to Index. It’s creating a token for us with the issuer name and issuer secret of our Service bus with the function GetToken.

Put the information about your Service Bus (Service Gateway, Issuer and Key) in the Settings.The default constructor load this information.

To update the list of our queues we will use a function Queues().  This will download the information from “$Resources/Queues” and build a array of Json object with properties: Name and Messages.  It took me some time before this Linq query works, the tricks is to use the namespace when looking for a node.

public class HomeController : Controller
{
    private String mServiceNamespace;
    private static String mBaseAddress;
    private static String mToken;
    private String mIssuerName;
    private String mIssuerSecret;

    private const String SBHOSTNAME = "servicebus.windows.net";
    private const String ACSHOSTNAME = "accesscontrol.windows.net";

    private const String ATOMNS = "{http://www.w3.org/2005/Atom}";
    private const String SBNS = "{http://schemas.microsoft.com/netservices/2010/10/servicebus/connect}";

    public HomeController()
    {

        mServiceNamespace = RoleEnvironment.GetConfigurationSettingValue("namespaceAddress");
        mIssuerName = RoleEnvironment.GetConfigurationSettingValue("issuerName");
        mIssuerSecret = RoleEnvironment.GetConfigurationSettingValue("issuerSecret");
        mBaseAddress = "https://" + mServiceNamespace + "." + SBHOSTNAME + "/";
    }

    public ActionResult Index()
    {

        try
        {
            // Get a SWT token from the Access Control Service, given the issuerName and issuerSecret values.
            mToken = GetToken(mIssuerName, mIssuerSecret);
        }
        catch (WebException we)
        {
            using (HttpWebResponse response = we.Response as HttpWebResponse)
            {
                if (response != null)
                {
                    ViewBag.Message += Environment.NewLine + (new StreamReader(response.GetResponseStream()).ReadToEnd());
                }
                else
                {
                    ViewBag.Message += Environment.NewLine + (we.ToString());
                }
            }
        }
        return View();
    }

    [HttpPost]
    public JsonResult CreateQueue(String queueName)
    {
        try
        {
            var _queueAddress = mBaseAddress + queueName;
            var _webClient = GetWebClient();

            var _putData = @"<entry xmlns=""http://www.w3.org/2005/Atom"">
                                <title type=""text"">" + queueName + @"</title>
                                <content type=""application/xml"">
                                <QueueDescription xmlns:i=""http://www.w3.org/2001/XMLSchema-instance"" xmlns=""http://schemas.microsoft.com/netservices/2010/10/servicebus/connect"" />
                                </content>
                             </entry>";

            byte[] _response = _webClient.UploadData(_queueAddress, "PUT", Encoding.UTF8.GetBytes(_putData));
            var _queueDescription = Encoding.UTF8.GetString(_response);

            return Json(_queueDescription, JsonRequestBehavior.AllowGet);
        }
        catch
        {
            return Json(false, JsonRequestBehavior.AllowGet);
        }
    }

    [OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
    public JsonResult Queues()
    {
        var _xDoc = XDocument.Parse(GetResources("$Resources/Queues"));

        var _queues = (from entry in _xDoc.Descendants(ATOMNS + "entry")
                       select new
                       {
                           Name = entry.Element(ATOMNS + "title").Value,
                           Messages = entry.Element(ATOMNS + "content").Element(SBNS + "QueueDescription").Element(SBNS + "MessageCount").Value
                       }).ToArray();

        return Json(_queues, JsonRequestBehavior.AllowGet);
    }

    private WebClient GetWebClient()
    {
        var _webClient = new WebClient();
        _webClient.Headers[HttpRequestHeader.Authorization] = mToken;
        return _webClient;
    }

    private String GetToken(String issuerName, String issuerSecret)
    {
        var acsEndpoint = "https://" + mServiceNamespace + "-sb." + ACSHOSTNAME + "/WRAPv0.9/";
        var realm = "http://" + mServiceNamespace + "." + SBHOSTNAME + "/";

        var _values = new NameValueCollection();
        _values.Add("wrap_name", issuerName);
        _values.Add("wrap_password", issuerSecret);
        _values.Add("wrap_scope", realm);

        var _webClient = new WebClient();
        byte[] response = _webClient.UploadValues(acsEndpoint, _values);

        var _responseString = Encoding.UTF8.GetString(response);

        var _responseProperties = _responseString.Split('&');
        var _tokenProperty = _responseProperties[0].Split('=');
        var _token = Uri.UnescapeDataString(_tokenProperty[1]);

        return "WRAP access_token=\"" + _token + "\"";
    }

    private String GetResources(String resourceAddress)
    {
 String _fullAddress = mBaseAddress + resourceAddress;
 var _webClient = GetWebClient();
 return _webClient.DownloadString(_fullAddress); ;
    }


}

Send a Message

On the client side using JQuery we add a submit event that will call SendMessage from our controller then update the status and the message count.

$(document).ready(function () {
    
    $("#sendMessage").submit(function (event) {
        event.preventDefault();
        var url = $(this).attr('action');
        var queueName = $("#sendMessageQueue option:selected").val();
        var message = $("#messageToSend").val();
        $(".loading").show();
        $("#create").attr("disabled", "true");
        $("#retrieve").attr("disabled", "true");
        $.post(url, { message: message, queueName: queueName })
            .success(function (response) {
                renderSendMessageStatus(response);
                updateMessageCountOf(queueName, response);
            })
            .error(function () { renderSendMessageStatus(false); });
    });
});


function updateMessageCountOf(queueName, numberOfMessages) {
    var message = numberOfMessages + " Messages";
    if (numberOfMessages == "0") message = "No Messages";
    if (numberOfMessages == "1") message = numberOfMessages + " Message";
    $("div.msgCountOf" + queueName.replace(/ /g, '') + " > label").html(message);
}

function renderSendMessageStatus(response) {
    if (response) $("#sendMessageStatus").html("Message sent successfully!");
    else $("#sendMessageStatus").html("An error occurred, please try again later.");
    $(".loading").hide();
    $("#create").attr("disabled", "");
    $("#retrieve").attr("disabled", "");
}

function updateMessageCountOf(queueName, numberOfMessages) {
    var message = numberOfMessages + " Messages";
    if (numberOfMessages == "0") message = "No Messages";
    if (numberOfMessages == "1") message = numberOfMessages + " Message";
    $("div.msgCountOf" + queueName.replace(/ /g, '') + " > label").html(message);
}

On the server side the SendMessage function will post our message. 
[HttpPost]
public JsonResult SendMessage(String queueName, String message)
{
    var _fullAddress = mBaseAddress + queueName + "/messages" + "?timeout=60";
    var _webClient = GetWebClient();

    _webClient.UploadData(_fullAddress, "POST", Encoding.UTF8.GetBytes(message));

    return Json("1", JsonRequestBehavior.AllowGet);
}

Retrieve a Message

Finally to retrieve a message wee need to select a queue then send it to the server side. I modify this part of the code because I’m not using the brokeredMessage so I don't have all the properties from the original code lab.

$(document).ready(function () {

$("#retrieveMessage").submit(function (event) {
        $("#noMessage").hide();
        $("#message").hide();
        event.preventDefault();
        var url = $(this).attr('action');
        var queueName = $("#retrieveMessageQueue option:selected").val();
        $(".loading").show();
        $("#send").attr("disabled", "true");
        $("#create").attr("disabled", "true");
        $.get(url, { queueName: queueName })
            .success(function (response) {
                renderMessage(response == null ? false : response.MessageInfo);
                updateMessageCountOf(queueName, response == null ? 0 : response.MessagesInQueue);
            })
            .error(function () { renderMessage(false); });
    });
});

function renderMessage(response) {
    if (response) {
        $("#body").html("<p>" + response + "</p>")
        $("#message").show();
    } else {
        $("#noMessage").show();
    }
    $(".loading").hide();
    $("#send").attr("disabled", "");
    $("#create").attr("disabled", "");
}

function updateMessageCountOf(queueName, numberOfMessages) {
    var message = numberOfMessages + " Messages";
    if (numberOfMessages == "0") message = "No Messages";
    if (numberOfMessages == "1") message = numberOfMessages + " Message";
    $("div.msgCountOf" + queueName.replace(/ /g, '') + " > label").html(message);
}

Than back to server side pretty strait forward retrieving the message from “queueName/messages/head"  without all the properties part. 

public JsonResult RetrieveMessage(String queueName)
{
    var _fullAddress = mBaseAddress + queueName + "/messages/head" + "?timeout=60";
    var _webClient = GetWebClient();

    byte[] response = _webClient.UploadData(_fullAddress, "DELETE", new byte[0]);
    var _message = Encoding.UTF8.GetString(response);

    return Json(new { MessageInfo = _message, MessagesInQueue = GetMessageCount(queueName) }, JsonRequestBehavior.AllowGet);
}


private String GetMessageCount(String queueName)
{
    var _xDoc = XDocument.Parse(GetResources("$Resources/Queues"));

    var _cnt = (from entry in _xDoc.Descendants(ATOMNS + "entry")
                where entry.Element(ATOMNS + "title").Value == queueName
                select entry.Element(ATOMNS + "content").Element(SBNS + "QueueDescription").Element(SBNS + "MessageCount").Value).FirstOrDefault();

    return _cnt;
}

Conclusion

This is just a lab so it’s not using all the best practice.  The goal was to try to convert the lab to use REST method… and it works.

~Franky


References