ASP.NET 4.5 and ASP.NET Core 1 Hosting BLOG

Tutorial and Articles about ASP.NET 4.0 and the latest ASP.NET 4.5 Hosting

ASP.NET Hosting - ASPHostPortal.com :: Convert DataTable To JSON String in ASP.NET

clock August 16, 2016 19:56 by author Armend

In this post we will explain about how to Convert DataTable To JSON String in ASP.NET . First of all you need to create an "ASP.NET Empty Web Site". Then use the following procedure.

 

Step 1

Create a ConvertDataTableToJson class in the App_Code folder and provide the following:

Convert DataTable To JSON String.       
    using System.Data 
    using System.Text; 
    public class ConvertDatatableToJson 
    { 
       public string DataTableToJson(DataTable dt) 
       { 
          DataSet ds = new DataSet(); 
          ds.Merge(dt); 
          StringBuilder JsonStr = new StringBuilder(); 
          if (ds != null && ds.Tables[0].Rows.Count > 0) 
          { 
             JsonStr.Append("["); 
             for (int i = 0; i < ds.Tables[0].Rows.Count; i++) 
             { 
                JsonStr.Append("{"); 
                for (int j = 0; j < ds.Tables[0].Columns.Count; j++) 
                { 
                   if (j < ds.Tables[0].Columns.Count - 1) 
                   { 
                      JsonStr.Append("\"" + ds.Tables[0].Columns[j].ColumnName.ToString() + "\":" + "\"" + ds.Tables[0].Rows[i][j].ToString() + "\","); 
                   } 
                   else if (j == ds.Tables[0].Columns.Count - 1) 
                   { 
                      JsonStr.Append("\"" + ds.Tables[0].Columns[j].ColumnName.ToString() + "\":" + "\"" + ds.Tables[0].Rows[i][j].ToString() + "\""); 
                   } 
                } 
                if (i == ds.Tables[0].Rows.Count - 1) 
                { 
                   JsonStr.Append("}"); 
                } 
                else    
                { 
                   JsonStr.Append("},"); 
                } 
             } 
             JsonStr.Append("]"); 
             return JsonStr.ToString(); 
          } 
          else 
          { 
             return null; 
          } 
       }

Step 2

Insert the grid view control into the Default.aspx page then write the following design code:

<asp:GridView ID="ui_grdVw_EmployeeDetail" runat="server" Width="50%" AutoGenerateColumns="false" HeaderStyle-CssClass="pageheading"> 
    <Columns> 
    <asp:TemplateField HeaderText="S.NO"> 
    <ItemTemplate> 
    <%#Container.DataItemIndex+1 %> 
    </ItemTemplate> 
    </asp:TemplateField> 
    <asp:TemplateField HeaderText="Employee ID"> 
    <ItemTemplate> 
    <asp:Label ID="ui_lbl_EmployeeID" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Emp_id") %>'></asp:Label> 
    </ItemTemplate> 
    </asp:TemplateField> 
    <asp:TemplateField HeaderText="Employee Name"> 
    <ItemTemplate> 
    <asp:Label ID="ui_lbl_EmployeeName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Emp_Name") %>'></asp:Label> 
    </ItemTemplate> 
    </asp:TemplateField> 
    <asp:TemplateField HeaderText="Employee Post"> 
    <ItemTemplate> 
    <asp:Label ID="ui_lbl_EmpJob" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Emp_job") %>'></asp:Label> 
    </ItemTemplate> 
    </asp:TemplateField> 
    <asp:TemplateField HeaderText="Department"> 
    <ItemTemplate> 
    <asp:Label ID="ui_lbl_Department" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Emp_Dep") %>'></asp:Label> 
    </ItemTemplate> 
    </asp:TemplateField> 
    </Columns> 
    </asp:GridView> 
    <br /> 
    <asp:Button ID="ui_btn_Convert1" runat="server" Text="Manually Convert To Json" OnClick="ui_btn_Convert1_Click" /><br /><br /><br /> 
    <asp:Label ID="ui_lbl_JsonString1" runat="server"></asp:Label>

Step 3

Now, open the Deafult.asps.cs then write the following code:
    using System; 
    using System.Data;
 

    public partial class _Default : System.Web.UI.Page 
    { 
       #region Global Variable 
       DataTable dt; 
       ConvertDatatableToJson dtJ; 
       string JsonString = string.Empty;    
       #endregion 
        
       protected void Page_Load(object sender, EventArgs e) 
       { 
          if (!IsPostBack) 
          { 
             ui_grdvw_EmployeeDetail_Bind(); 
          } 
       }       
       protected void ui_grdvw_EmployeeDetail_Bind() 
       { 
          dt = new DataTable(); 
          EmployeeRecord employeeRecord = new EmployeeRecord(); 
          dt = employeeRecord.EmpRecord(); 
          ViewState["dt"] = dt; 
          ui_grdVw_EmployeeDetail.DataSource = dt; 
          ui_grdVw_EmployeeDetail.DataBind(); 
       }       
       protected void ui_btn_Convert1_Click(object sender, EventArgs e) 
       { 
          dtJ = new ConvertDatatableToJson(); 
          JsonString = dtJ.DataTableToJson((DataTable)ViewState["dt"]); 
          ui_lbl_JsonString1.Text = JsonString; 
       } 
    }

Step 4

Press F5, run the project.

Now, convert the DataTable to a JSON string using the newtonsoft DLL.

Step 1

Download the Newtonsoft DLL and move it to the ASP.Net project's bin folder.

Step 2

Then, insert a button and label UI Control in the Deafult.aspx page as in the following:

<asp:Button ID="iu_btn_Convert2" runat="server" Text="Newtonsoft Convert To Json" OnClick="iu_btn_Convert2_Click" /> 
    <br /> 
    <br /> 
    <asp:Label ID="ui_lbl_JsonString2" runat="server"></asp:Label>

Step 3

Now, write the following code in Default.aspx.cs:
using this namespace

using Newtonsoft.Json;

And then:

protected void iu_btn_Convert2_Click(object sender, EventArgs e) 
    { 
       dt = (DataTable)ViewState["dt"]; 
       JsonString = JsonConvert.SerializeObject((DataTable)ViewState["dt"]); 
       ui_lbl_JsonString2.Text = JsonString; 
    }

Now, run the project and click on the Newtonsoft Convert to JSON     

Best ASP.NET Hosting Recommendation

ASPHostPortal.com provides its customers with Plesk Panel, one of the most popular and stable control panels for Windows hosting, as free. You could also see the latest .NET framework, a crazy amount of functionality as well as Large disk space, bandwidth, MSSQL databases and more. All those give people the convenience to build up a powerful site in Windows server. ASPHostPortal.com offers ASP.NET hosting starts from $1/month only. They also guarantees 30 days money back and guarantee 99.9% uptime. If you need a reliable affordable ASP.NET Hosting, ASPHostPortal.com should be your best choice.   

 



ASP.NET Hosting - ASPHostPortal.com :: Asp.net Export Excel Show/Hide Loading image

clock August 2, 2016 19:58 by author Armend

This Tip will explain how to hide the loading gif image after the file is downloaded . It  will be helpful when we are using  Response Object to export the excel or any other file format.

 

Sometimes while  downloading an excel or any file from an Asp application, it might take some time to Generate the File, the delay  depends on many factors( file size, loops, server bandwidth etc ). So we repesent the File Generation process using a rotating GIF image next to the button.
But when we are using Response object we wont get the event after the file is downloaded to the browser, in this case it will be difficult to hide the loading gif which is being shown on the screen

The below steps will guide how to  Show the Gif while Generating and hide it once the file is completly downloaded.

Hide the GIF after download

  • When the download button is clicked, show the loading gif image using onclicentClick event and CSS properties
  • On the Client click event invoke a Javascript method which Contains a  Setinterval  object that moniters  for our cookie (created in c# Response object).
  • In the Server button click Event Create an HttpCookie and append it to the Respone object.
  • So when the File is downloaded completly the Cookie is added to the Page, Now the SetInterval function will capture the cookie and Hides the Loading Gif image.
  • Note: whenever the download button is clicked, previous cookie has to be deleted.

Using the code

protected void btnExportExcel_Click(object sender, EventArgs e)
          {
            DataTable dt = new DataTable();
            dt = GetDataFromDb();
            System.Threading.Thread.Sleep(3000); // for testing purpose to create 3 seconds delay
            //Create a temp GridView
            GridView gv = new GridView();
            gv.AllowPaging = false;
            gv.DataSource = dt;
            gv.DataBind();
            Response.Clear();
            Response.Buffer = true;
            Response.AddHeader("content-disposition", "attachment;filename=ExcelReport.xls");
            Response.Charset = "";
            Response.ContentType = "application/vnd.ms-excel";
            StringWriter sw = new StringWriter();
            HtmlTextWriter hw = new HtmlTextWriter(sw);
            gv.RenderControl(hw);
            // Append cookie
            HttpCookie cookie = new HttpCookie("ExcelDownloadFlag");
            cookie.Value = "Flag";
            cookie.Expires = DateTime.Now.AddDays(1);
            Response.AppendCookie(cookie);
            // end
            Response.Output.Write(sw.ToString());
            Response.Flush();
            Response.End();
        }

HTML/ASPX Code

<table>
            <tr>
                <td>
                    <asp:Button Text="Download" ID="btnExportExcel" OnClientClick="jsShowHideProgress();" runat="server" OnClick="btnExportExcel_Click" />
                </td>
                <td>
                    <img style="display: none" id="imgloadinggif" src="Images/loading.gif" alt="loading.." />
                </td>
            </tr>
        </table>

Javascript Code:

function jsShowHideProgress() {
    setTimeout(function () { document.getElementById('imgloadinggif').style.display = 'block'; }, 200);
    deleteCookie();

    var timeInterval = 500; // milliseconds (checks the cookie for every half second )

    var loop = setInterval(function () {
        if (IsCookieValid())
        { document.getElementById('imgloadinggif').style.display = 'none'; clearInterval(loop) }

    }, timeInterval);
}

// cookies
function deleteCookie() {
    var cook = getCookie('ExcelDownloadFlag');
    if (cook != "") {
        document.cookie = "ExcelDownloadFlag=; Path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC";
    }
}

function IsCookieValid() {
    var cook = getCookie('ExcelDownloadFlag');
    return cook != '';
}

function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) == 0) {
            return c.substring(name.length, c.length);
        }
    }
    return "";
}

About ASPHostPortal.com:

ASPHostPortal.com is The Best, Cheap and Recommended ASP.NET & Linux Hosting. ASPHostPortal.com has ability to support the latest Microsoft, ASP.NET, and Linux technology, such as: such as: WebMatrix, Web Deploy, Visual Studio, Latest ASP.NET Version, Latest ASP.NET MVC Version, Silverlight and Visual Studio Light Switch, Latest MySql version, Latest PHPMyAdmin, Support PHP, etc. Their service includes shared hosting, reseller hosting, and Sharepoint hosting, with speciality in ASP.NET, SQL Server, and Linux solutions. Protection, trustworthiness, and performance are at the core of hosting operations to make certain every website and software hosted is so secured and performs at the best possible level.



ASP.NET Hosting - ASPHostPortal.com :: How to Check Duplicate User Names In ASP.NET Web Pages Sites

clock October 5, 2015 11:39 by author Kenny

How to Check Duplicate User Names In ASP.NET Web Pages Sites

The Web Pages Starter Site template provides a useful starting point for developing a Razor Web Pages site that includes membership. But it doesn't include any mechanism for preventing duplicate user names. This article offers one solution to the problem that uses jQuery.

If you ask how to prevent duplicate user names in forums, one of the suggestions that is often put forward is to apply a unique constraint in the database column that holds the user name. Any attempt to submit a duplicate value will result in an exception being raised in the relevant database provider. You can catch this exception and show the user an appropriate message. This works but it's a fairly clunky solution. And many people feel that you should not use exceptions as a means to manage your business rules.

The solution featured in this article uses AJAX to query the database and to give the user immediate feedback when they enter their chosen user name. The AJAX call requests a page that exists purely to query the database to see if the selected user name is already in use. The solution also includes a server side chekc to ensure that users who have disabled JavaScript so not slip through the net. The solution requires a couple of amendments to the Register.cshtml file in the Starter Site, and the addition of 3 files. But first, the changes to the Register.cshtml page. The first change is in the inclusion of a JavaScript file called dupecheck.js.

@* Remove this section if you are using bundling *@
@section Scripts {
    <script src="~/Scripts/jquery.validate.min.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.min.js"></script>
    <script src="~/Scripts/dupecheck.js"></script>
}

And the second is the server side check to see if the username is in use:

if(Functions.IsDuplicate(email)){
    ModelState.AddError("email", "User name is already taken");
}

I placed this in the if(IsPost) section just after the initial variables that represent the submitted values (email, password and confirmPassword) are declared. The code calls a function named IsDuplicate. The function is declared in a file called Functions.cshtml which is placed in a folder called App_Code:

@functions {
    public static bool IsDuplicate(string username){
        var db = Database.Open("StarterSite");
        var commandText = @"SELECT COUNT(Email) FROM UserProfile WHERE Email = @0";
        return (int)db.QueryValue(commandText, username) > 0;
    }
}

Note that the name of the folder is important. The function returns a bool. The value of the bool is determined as a result if the SQL query which gets a count of the rows containing the provided user name. By default, the Starter Site uses a column called Email in the UserProfile table for the storage of user names. This function is also called in a separate file named DupeCheck.cshtml. This file is placed in the root of the site:

@{
    Layout = null;
    if(IsAjax){
        var username = Request["username"];
        var result = Functions.IsDuplicate(username);
        Json.Write(new { isDupe = result }, Response.Output);
    }
}

DupeCheck.cshtml is designed to work exclusively with AJAX. The code includes an instruction to nullify any layout pages that might have been set in a _PageStart file, and then it uses the IsAjax property to determine if the page has been requested via an AJAX call. If it has, it uses the IsDuplicate method to check the availability of the posted username and returns the result to the calling code. The result is an anonymous type that has one propery: isDupe, which is a boolean. The anonymous type is serialised to JSON by the Json helper.

The final part of the solution is the dupecheck.js file. This uses jQuery:

$(function () {
    $('#email').change(function () {
        $.post(
            '/DupeCheck',
            { username: $(this).val() },
            function (data) {
                var emailValidation = $('span[data-valmsg-for="email"]');
                if (data.isDupe) {
                    if (emailValidation.hasClass('field-validation-valid')) {
                        emailValidation.removeClass('field-validation-valid');
                        emailValidation.addClass('field-validation-error');
                        emailValidation.text('That name is already taken!');
                    }
                } else {
                    if (emailValidation.hasClass('field-validation-error')) {
                        emailValidation.removeClass('field-validation-error');
                        emailValidation.addClass('field-validation-valid');
                        emailValidation.text('');
                    }
                }
            },'json'
        );
    });
});

An event handler is attached to the change event of the user name input (which has an id if email in the Starter Site). The current value is posted to the DupeCheck.cshtml page via AJAX. The code above checks the response from the server to see if the value is a duplicate, and if it is, an appropriate error message is displayed to the user.

Best ASP.NET 4.6 Hosting Recommendation

ASPHostPortal.com provides its customers with Plesk Panel, one of the most popular and stable control panels for Windows hosting, as free. You could also see the latest .NET framework, a crazy amount of functionality as well as Large disk space, bandwidth, MSSQL databases and more. All those give people the convenience to build up a powerful site in Windows server. ASPHostPortal.com offers ASP.NET hosting starts from $1/month only. They also guarantees 30 days money back and guarantee 99.9% uptime. If you need a reliable affordable ASP.NET Hosting, ASPHostPortal.com should be your best choice.



ASP.NET MVC 6 Hosting - ASPHostPortal :: Remote Validation in ASP.NET MVC

clock August 24, 2015 08:07 by author Kenny

Remote Validation in ASP.NET MVC

ASP.NET is an open-source server-side Web application framework designed for Web development to produce dynamic Web pages. It was developed by Microsoft to allow programmers to build dynamic web sites, web applications and web services. ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that enables a clean separation of concerns and that gives you full control over markup. Remote validation is used to make server calls to validate data without posting the entire form to the server when server side validation is preferable to client side.  It's all done set up model and controller which is pretty neat. 

Using the Code

To implement remote validation in an application we have two scenarios, one is without an additional parameter and the other is with an additional parameter. First we create an example without an additional parameter. In this example we check whether a username exists or not. If the username exists then that means the input user name is not valid. We create a view model class "UserViewModel" under the Models folder and that code is:

using System.Web.Mvc;  
namespace RemoteValidation.Models   
{  
    public class UserViewModel   
    {  
        public string UserName   
        {  
            get;  
            set;  
        }  
        public string Email   
        {  
            get;  
            set;  
        }  
    }  
}

 

Now we create a static data source, in other words we create a static list of UserViewModel in which we could check whether a username exists or not. You can also use the database rather than a static list. The following code snippet is for StaticData.

using RemoteValidation.Models;  
using System.Collections.Generic;  
 
namespace RemoteValidation.Code   
{  
    public static class StaticData   
    {  
        public static List < UserViewModel > UserList   
        {  
            get {  
                return new List < UserViewModel >   
                {  
                    new UserViewModel   
                    {  
                        UserName = "User1", Email = "[email protected]"  
                    },  
                    new UserViewModel   
                    {  
                        UserName = "User2", Email = "[email protected]"  
                    }  
                }  
            }  
        }  
    }  

 

Now we create a controller "ValidationController" in which we create an action method to check whether a user name exists or not and return a result as a JSON format. If the username exists then it returns false so that the validation is implemented on the input field. The following code snippet shows ValidationController under the Controllers folder.

using RemoteValidation.Code;  
using System.Linq;  
using System.Web.Mvc;  
 
namespace RemoteValidation.Controllers   
{  
    public class ValidationController: Controller   
    {  
        [HttpGet]  
        public JsonResult IsUserNameExist(string userName)   
        {  
            bool isExist = StaticData.UserList.Where(u = > u.UserName.ToLowerInvariant().Equals(userName.ToLower())).FirstOrDefault() != null;  
            return Json(!isExist, JsonRequestBehavior.AllowGet);  
        }  
    }  
}

 

Now we add remote validation on the UserName of the UserViewModel property as in the following code snippet.

using System.Web.Mvc;  
 
namespace RemoteValidation.Models   
{  
    public class UserViewModel   
    {  
        [Remote("IsUserNameExist", "Validation", ErrorMessage = "User name already exist")]  
        public string UserName   
        {  
            get;  
            set;  
        }  
        public string Email   
        {  
            get;  
            set;  
        }  
    }  

 

As in the preceding code snippet, the IsUserNameExist is a method of ValidationController that is called on the blur of an input field using a GET request. Now we create UserController under the Controllers folder to render a view on the UI.

using RemoteValidation.Models;  
using System.Web.Mvc;  
 
namespace RemoteValidation.Controllers   
{  
    public class UserController: Controller   
    {  
        [HttpGet]  
        public ActionResult AddUser()   
        {  
            UserViewModel model = new UserViewModel();  
            return View(model);  
        }  
    }  

Now we add jquery.validate.js and jquery.validate.unobtrusive.js to the project and create a bundle as in the following code snippet.

using System.Web.Optimization;  
 
namespace RemoteValidation.App_Start   
{  
    public class BundleConfig   
    {  
        public static void RegisterBundles(BundleCollection bundles)   
        {  
            bundles.Add(new StyleBundle("~/Content/css").Include(  
                "~/Content/css/bootstrap.css",  
                "~/Content/css/font-awesome.css",  
                "~/Content/css/site.css"));  
 
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(  
                "~/Scripts/jquery-{version}.js"));  
 
            bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include(  
                "~/Scripts/jquery.validate*"));  
        }  
    }  

Thereafter we add the following keys in the web.config file.

<add key="ClientValidationEnabled" value="true" />   
<add key="UnobtrusiveJavaScriptEnabled" value="true" />  
 
 

Thereafter we create a view for the AddUser action method. The following code snippet is for the AddUser view.

@model RemoteValidation.Models.UserViewModel  
 
< div class = "panel panel-primary" > < div class = "panel-heading panel-head" > Add User < /div>    
    <div class="panel-body">    
        @using (Html.BeginForm())    
        {    
            <div class="form-horizontal">    
                <div class="form-group">    
                    @Html.LabelFor(model => model.UserName, new { @class = "col-lg-2 control-label" })    
                    <div class="col-lg-9">    
                        @Html.TextBoxFor(model => model.UserName, new { @class = "form-control" })    
                        @Html.ValidationMessageFor(model => model.UserName)    
                    </div > < /div>    
                <div class="form-group">    
                    @Html.LabelFor(model => model.Email, new { @class = "col-lg-2 control-label" })    
                    <div class="col-lg-9">    
                        @Html.TextBoxFor(model => model.Email, new { @class = "form-control" })    
                        @Html.ValidationMessageFor(model => model.Email)    
                    </div > < /div>                    
                <div class="form-group">    
                    <div class="col-lg-9"></div > < div class = "col-lg-3" > < button class = "btn btn-success"  
                     id = "btnSubmit"  
                     type = "submit" > Submit < /button>    
                    </div >
               < /div>    
            </div >  
} < /div>    
</div >   
@section scripts   
{  
    @Scripts.Render("~/bundles/jqueryval")  

Let's run the application and put values into the user name field to execute the remote validation as in the following image.

Figure 1: Remote validation on user name


Now we move to another option, we pass an additional parameter in the remote validation. We pass both the user name and email as a parameter and check whether the username and email combination exist or not on the email input. That's why we add one more method in ValidationController as in the following code snippet for it.

[HttpGet]  
public JsonResult IsUserExist(string email, string userName)   
{  
    bool isExist = StaticData.UserList.Where(u = > u.UserName.ToLowerInvariant().Equals(userName.ToLower()) && u.Email.ToLowerInvariant().Equals(email.ToLower())).FirstOrDefault() != null;  
    return Json(!isExist, JsonRequestBehavior.AllowGet);  

Now we call this method on the Email property of UserViewModel as in the following code snippet.

using System.Web.Mvc;  
 
namespace RemoteValidation.Models   
{  
    public class UserViewModel   
    {  
        [Remote("IsUserNameExist", "Validation", ErrorMessage = "User name already exist")]  
        public string UserName   
        {  
            get;  
            set;  
        }  
        [Remote("IsUserExist", "Validation", ErrorMessage = "User already exist", AdditionalFields = "UserName")]  
        public string Email   
        {  
            get;  
            set;  
        }  
    }  
}

As in the preceding code snippet, we are passing an additional field using AdditionalFields in Remote. If we must pass more than one parameter then these will be comma-separated. Now run the application and the result will be as shown in the following image.  



ASP.NET MVC SignalR Hosting - ASPHostPortal.com :: Create a Real-Time Message Board Making use of ASP.Net MVC 5, SignalR 2, and KnockoutJS

clock October 28, 2014 06:05 by author Ben

Have you ever questioned how Facebook sends you notifications the instant you receive a new information, friend request, or remark? Does the customer constantly look for new events? Doesn’t that consume a whole lot of memory within the user’s side? What sort of pressure does that place on Facebook’s servers?


 

Due to HTMl five as well as the support of web sockets in modern browsers, this performance can be achieved with out over-taxing the user or even the server. Leveraging a library like SignalR for .NET or Socket.IO for Node.js, most of the very hard perform around working with web sockets is already completed to suit your needs.

On this tutorial, we’re planning to build a real-time concept board, very similar to Facebook. Although this will not be something you should model and drive to manufacturing as-is, it could supply you with the fundamental groundwork for creating your own personal real-time net application.

Let's Start

Start the Project - Initial, begin a new ASP.Net MVC 5 project from Visual Studio 2013. You can title it what ever you want, but I named the undertaking “MessageBoardTutorial”. Make sure you place a checkmark close to "Web API".


Get dependencies with NuGet - Let’s go on and get downloading our required libraries out of the best way. We can get every thing with NuGet, saving us plenty of your time. Within the Remedy Explorer, right-click around the project name and click on “Manage NuGet Packages…” from the context menu.

Initial, you'll want to update all the packages presently set up to their newest variations. Be aware that because MVC 4, all the MVC libraries are bin deployed, so you will need to update them when commencing a fresh undertaking. On the still left, simply click on “Updates->nuget.org” and also you will see each of the offers that must be up-to-date. Just click on on “Update All” and allow NuGet do its thing.


When that's done, near the window. Open up the Package Supervisor Console in Tools > NuGet Package Manager > Package Manager Console. We must set up a few a lot more deals for this tutorial. Run the subsequent commands to set up the deals we need for this tutorial.

PM> Install-Package EntityFramework
PM> Install-Package Microsoft.AspNet.SignalR
PM> Install-Package Moment.js
PM> Install-Package KnockoutJS

NuGet will put in several dependencies that SignalR 2 needs. Additionally, you will get yourself a good tiny readme.txt. Feel free to read this, but we are going to be covering this listed here also.

The Front End

We are going to now truly commence coding. The Layout - First, we've got to go into the structure file and simplify issues somewhat - we don't truly require the responsive menu for this tutorial. Open /Views/Shared/_Layout.cshtml. It ought to now search such as this, assuming you failed to modify the default directories:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/modernizr")
</head>
<body>
    <div class="container body-content">
        @RenderBody()
    </div>
 
    @Scripts.Render("~/bundles/jquery")
    @Scripts.Render("~/bundles/bootstrap")
    @RenderSection("scripts", required: false)
</body>
</html>

Edit the Home Controller and Index View - We will only need a single controller and view for this software. Inside the Remedy Explorer, open Controllers > HomeController and take away all Steps except for Index.

Now, open up the Index check out and just delete every thing. If you are a neat freak like me, truly feel totally free to eliminate another views inside the Views > Home.

Edit the View - Under is the see for your application. In case you are new to KnockoutJS, a few of this may appear unfamiliar. I will clarify a lot more when we get to the JavaScript inside the up coming section. Just be aware that wherever the thing is a "data-bind" attribute, the component is joined into a JS worth we are tracking with Knockout.

We're mostly using regular CSS courses from Bootstrap. Bootstrap gives us a quick way to incorporate a responsive grid framework for our view. The still left column includes our "login" type and also the proper the information board itself.

@{
    ViewBag.Title = "Land of Ooobook";
}
 
<div class="jumbotron">
    <h1>Land of Ooobook</h1>
    <p>Candy Kingdom's Social Network</p>
</div>
 
<div class="container">
    <div class="row">
        <div class="col-md-4">
            <form class="pad-bottom" data-bind="visible: !signedIn(), submit: signIn">
                <div class="form-group">
                    <label for="username">Sign In</label>
                    <input class="form-control" type="text" name="username" id="username" placeholder="Enter your userame" />
                </div>
                <button type="submit" class="btn btn-primary">Sign In</button>
                <br />
            </form>
 
            <div data-bind="visible: signedIn">
                <p>You are signed in as <strong data-bind="text: username"></strong></p>
            </div>
        </div>
        <div class="col-md-8">
            <div data-bind="visible: notifications().length > 0, foreach: notifications">
                <div class="summary alert alert-success alert-dismissable">
                    <button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
                    <p data-bind="text: $data"></p>
                </div>
            </div>
 
            <div class="new-post pad-bottom" data-bind="visible: signedIn">
                <form data-bind="submit: writePost">
                    <div class="form-group">
                        <label for="message">Write a new post:</label>
                        <textarea class="form-control" name="message" id="message" placeholder="New post"></textarea>
                    </div>
                    <button type="submit" class="btn btn-default">Submit</button>
                </form>
            </div>
 
            <ul class="posts list-unstyled" data-bind="foreach: posts">
                <li>
                    <p>
                        <span data-bind="text: username" class="username"></span><br />
                    </p>
                    <p>
                        <span data-bind="text: message"></span>
                    </p>
 
                    <p class="no-pad-bottom date-posted">Posted <span data-bind="text: moment(date).calendar()" /></p>
 
                    <div class="comments" data-bind="visible: $parent.signedIn() || comments().length > 0">
                        <ul class="list-unstyled" data-bind="foreach: comments, visible: comments().length > 0">
                            <li>
 
                                <p>
                                    <span class="commentor" data-bind="text: username"></span>
                                    <span data-bind="text: message"></span>
                                </p>
                                <p class=" no-pad-bottom date-posted">Posted <span data-bind="text: moment(date).calendar()" /></p>
                            </li>
                        </ul>
 
                        <form class="add-comment" data-bind="visible: $parent.signedIn, submit: addComment">
                            <div class="row">
                                <div class="col-md-9">
                                    <input type="text" class="form-control" name="comment" placeholder="Add a comment" />
                                </div>
                                <div class="col-md-3">
                                    <button class="btn btn-default" type="submit">Add Comment</button>
                                </div>
                            </div>
                        </form>
                    </div>
                </li>
            </ul>
        </div>
    </div>
 
</div>
 
@section scripts {
    <script src="~/Scripts/moment.js"></script>
    <script src="~/Scripts/jquery.signalR-2.0.3.min.js"></script>
    <script src="~/signalr/hubs"></script>
    <script src="~/Scripts/knockout-3.1.0.js"></script>
    <script src="~/Scripts/board.js"></script>
}

Add a bit of CSS - We have a few custom CSS classes on top of what Bootstrap provides. Currently, /Content/Site.css is in your style bundle. Open it and replace everything above the validation helper classes with this:

.pad-bottom {
    margin-bottom: 10px;
}
 
.no-pad-bottom {
    margin-bottom: 0;
}
 
.new-post {
    background-color: #c9e0fc;
    padding: 15px 10px;
}
 
.username {
    font-weight: bold;
    color: #ff6a00;
}
 
.commentor {
    font-weight: bold;
    color: #004bff;
}
 
.posts li .date-posted {
    font-size: 12px;
    font-style: italic;
}
 
.posts li {
    border-bottom: 1px solid #CCC;
    padding: 15px 0;
}
 
.posts li:first-child {
    border-top: 1px solid #CCC;
}
 
.posts .comments {
    background-color: #efefef;
    margin-top: 10px;
    padding: 10px;
    padding-left: 30px;
}
 
.posts .comments li {
    padding-top: 10px;
    border: 0;
}
 
form.add-comment  {
    margin-top: 10px;
    margin-bottom: 10px;
}

The JavaScript

Create a script - In the Scripts directory, make a new script called board.js. This script will contain the client-side logic for the application.

Edit the script - Let's begin with our script.

A message board is made of posts and comments to those posts. Let's define those objects.

var post = function (id, message, username, date) {
    this.id = id;
    this.message = message;
    this.username = username;
    this.date = date;
    this.comments = ko.observableArray([]);
 
    this.addComment = function (context) {
        var comment = $('input[name="comment"]', context).val();
        if (comment.length > 0) {
            $.connection.boardHub.server.addComment(this.id, comment, vm.username())
            .done(function () {
                $('input[name="comment"]', context).val('');
            });
        }
    };
}
 
var comment = function (id, message, username, date) {
    this.id = id;
    this.message = message;
    this.username = username;
    this.date = date;
}

A submit has an observable variety of remarks. This enables it in order that when new remarks come in, it's immediately displayed within the view.

We've outlined our submit and remark objects. Now let's define our view design that is the glue from the application.

var vm = {
    posts: ko.observableArray([]),
    notifications: ko.observableArray([]),
    username: ko.observable(),
    signedIn: ko.observable(false),
    signIn: function () {
        vm.username($('#username').val());
        vm.signedIn(true);
    },
    writePost: function () {
        $.connection.boardHub.server.writePost(vm.username(), $('#message').val()).done(function () {
            $('#message').val('');
        });
    },
}
 
ko.applyBindings(vm);

We have an observable array of posts (which have an observable array of remarks). We even have an observable assortment of notifications, which inform customers of latest posts or comments on their posts. Our view model tracks the username and if a user is signed in. Finally, a view design can include techniques.

Next, we've a way for loading posts, which is known as when the web page hundreds and the user connects into a SignalR hub. The posts are loaded from the Net API controller which we are going to make later. Each and every submit is additional to the observable assortment of posts. Each and every from the post's feedback are added to the comments observable variety of the submit. This really is a really verbose method of performing this, but I wanted to make it distinct what was happening right here.

function loadPosts() {
$.get('/api/posts', function (data) {
    var postsArray = [];
    $.each(data, function (i, p) {
        var newPost = new post(p.Id, p.Message, p.Username, p.DatePosted);
        $.each(p.Comments, function (j, c) {
            var newComment = new comment(c.Id, c.Message, c.Username, c.DatePosted);
            newPost.comments.push(newComment);
        });
 
        vm.posts.push(newPost);
        });
    });
}

The rest of the script has to do with SignalR connections and methods. We'll get back to that later. Below is the entire board.js script.

var post = function (id, message, username, date) {
    this.id = id;
    this.message = message;
    this.username = username;
    this.date = date;
    this.comments = ko.observableArray([]);
 
    this.addComment = function (context) {
        var comment = $('input[name="comment"]', context).val();
        if (comment.length > 0) {
            $.connection.boardHub.server.addComment(this.id, comment, vm.username())
            .done(function () {
                $('input[name="comment"]', context).val('');
            });
        }
    };
}
 
var comment = function (id, message, username, date) {
    this.id = id;
    this.message = message;
    this.username = username;
    this.date = date;
}
 
var vm = {
    posts: ko.observableArray([]),
    notifications: ko.observableArray([]),
    username: ko.observable(),
    signedIn: ko.observable(false),
    signIn: function () {
        vm.username($('#username').val());
        vm.signedIn(true);
    },
    writePost: function () {
        $.connection.boardHub.server.writePost(vm.username(), $('#message').val()).done(function () {
            $('#message').val('');
        });
    },
}
 
ko.applyBindings(vm);
 
function loadPosts() {
    $.get('/api/posts', function (data) {
        var postsArray = [];
        $.each(data, function (i, p) {
            var newPost = new post(p.Id, p.Message, p.Username, p.DatePosted);
            $.each(p.Comments, function (j, c) {
                var newComment = new comment(c.Id, c.Message, c.Username, c.DatePosted);
                newPost.comments.push(newComment);
            });
 
            vm.posts.push(newPost);
        });
    });
}
 
$(function () {
    var hub = $.connection.boardHub;
    $.connection.hub.start().done(function () {
        loadPosts(); // Load posts when connected to hub
    });
 
    // Hub calls this after a new post has been added
    hub.client.receivedNewPost = function (id, username, message, date) {
        var newPost = new post(id, message, username, date);
        vm.posts.unshift(newPost);
 
        // If another user added a new post, add it to the activity summary
        if (username !== vm.username()) {
            vm.notifications.unshift(username + ' has added a new post.');
        }
    };
 
    // Hub calls this after a new comment has been added
    hub.client.receivedNewComment = function (parentPostId, commentId, message, username, date) {
        // Find the post object in the observable array of posts
        var postFilter = $.grep(vm.posts(), function (p) {
            return p.id === parentPostId;
        });
        var thisPost = postFilter[0]; //$.grep returns an array, we just want the first object
 
        var thisComment = new comment(commentId, message, username, date);
        thisPost.comments.push(thisComment);
 
        if (thisPost.username === vm.username() && thisComment.username !== vm.username()) {
            vm.notifications.unshift(username + ' has commented on your post.');
        }
    };
});

The Data Layer - We will be making use of Entity Framework as well as the Code First sample for our straightforward info layer.

Inside the Models directory, develop a brand new C# class referred to as MessageBoard.cs. Our data designs are little, and in our scenario we'll just place them in a single file alongside with all the data context.

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data.Entity;
using System.Linq;
using System.Web;
 
namespace MessageBoardTutorial.Models
{
    public class MessageBoardContext : DbContext
    {
        public DbSet<Post> Posts { get; set; }
        public DbSet<Comment> Comments { get; set; }
    }
 
    public class Post
    {
        [Key]
        public int Id { get; set; }
        public string Message { get; set; }
        public string Username { get; set; }
        public DateTime DatePosted { get; set; }
        public virtual ICollection<Comment> Comments { get; set; }
    }
 
    public class Comment
    {
        [Key]
        public int Id { get; set; }
        public string Message { get; set; }
        public string Username { get; set; }
        public DateTime DatePosted { get; set; }
        public virtual Post ParentPost { get; set; }
    }
}

Although the actual database doesn't yet exist, it will likely be produced if the application deems it essential. Should you maintain your internet.config unchanged, it's going to develop it within your LocalDB instance of SQL Server Specific.

The API

The script requirements a technique to get in touch with to get the posts to the concept board. Whilst we could just tack a technique on to our HomeController that would try this, we can equally as effortlessly create an ASP.Web Internet API controller which will fetch and immediately convert the posts into a JSON format.

Create the API Controller - In the Solution Explorer, right click on the Controllers directory and click on Add > Web API Controller Class (v2) in the context menu. Add a new Web API controller and call it PostsController.cs

Write the API
- Replace the code with the below. Our API will simply return a JSON or XML-serialized array of all of the posts and comments on the message board when a client calls http://[yoursite]/api/posts.

using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http;
    using MessageBoardTutorial.Models;
 
    namespace MessageBoardTutorial.Controllers
    {
        public class PostsController : ApiController
        {
            private MessageBoardContext _ctx;
            public PostsController()
            {
                this._ctx = new MessageBoardContext();
            }
 
            // GET api/<controller>
            public IEnumerable<post> Get()
            {
                return this._ctx.Posts.OrderByDescending(x => x.DatePosted).ToList();
            }
        }
    }
</post></controller>

Handle circular references - If you look at our data models, a Post contains a virtual collection of comments, and a Comment contains a virtual Post that refers to the comment's parent. This circular reference will freak out Web API's serialization method. To solve this, just add the following line of code to the Register method in the WebApiConfig class located at App_Start/WeApiConfig.cs
   
config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling =
    Newtonsoft.Json.ReferenceLoopHandling.Ignore;

Circular references will now be ignored.

Implementing the SignalR Hub

SignalR provides a relationship between clientele and also the server. Clients connect to a SignalR Hub. The Hub can then contact client-side occasions on a single, some, or all related clients. The Hub tracks which consumers are linked to it. This can be the center of real-time net programs. Within our case, a client generates a fresh submit or comment, which phone calls a method around the Hub. The Hub then calls a method on all of the message board's connected users that inserts the brand new submit or remark.

In a nutshell, the awesomeness of SignalR is that it may call JavaScript capabilities on any browser linked to it. The outdated assemble is clientele could only get in touch with server-side features. This type of functionality could only be achieved via long-polling (a customer working an infinite loop that calls a server method).


Newer browsers connect to hubs via HTML 5 web sockets. For older browsers, there are long-polling and "forever frame" fallbacks.

Map the hubs - In order for SignalR to begin and for the web application to map the connection hubs, we must create an OWIN startup class. Lucky for us, this just involves a couple of clicks and a line of code. Right-click on the solution and add a new item. Find the OWIN Startup Class template. Name this file "Startup.cs". Now, you just have to add one line of code in the Configuration method to map the hubs.

using System;
using System.Threading.Tasks;
using Microsoft.Owin;
using Owin;
 
[assembly: OwinStartup(typeof(MessageBoardTutorial.Startup))]
 
namespace MessageBoardTutorial
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            app.MapSignalR();
        }
    }
}

Create the Hub - Make a new directory in the root of your project called Hubs. Now, right-click on this new directory and click on Add > New Item... in the context menu. Create a new SignalR Hub Class called BoardHub.cs.


Replace the code in the file with the below:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Microsoft.AspNet.SignalR;
using MessageBoardTutorial.Models;
 
namespace MessageBoardTutorial.Hubs
{
    public class BoardHub : Hub
    {
        public void WritePost(string username, string message)
        {
            var ctx = new MessageBoardContext();
            var post = new Post { Message = message, Username = username, DatePosted = DateTime.Now };
            ctx.Posts.Add(post);
            ctx.SaveChanges();
 
            Clients.All.receivedNewPost(post.Id, post.Username, post.Message, post.DatePosted);
        }
 
        public void AddComment(int postId, string comment, string username)
        {
            var ctx = new MessageBoardContext();
            var post = ctx.Posts.FirstOrDefault(p => p.Id == postId);
 
            if (post != null)
            {
                var newComment = new Comment { ParentPost = post, Message = comment, Username = username, DatePosted = DateTime.Now };
                ctx.Comments.Add(newComment);
                ctx.SaveChanges();
 
                Clients.All.receivedNewComment(newComment.ParentPost.Id, newComment.Id, newComment.Message, newComment.Username, newComment.DatePosted);
            }
        }
    }

}

The Hub contains a method for writing a new post and a method for writing a new comment. Both methods are called from the client and ultimately call client-side methods for connected users.

For example, the writePost client-side method is called when a user writes a new post:

writePost: function () {
    $.connection.boardHub.server.writePost(vm.username(), $('#message').val()).done(function () {
        $('#message').val('');
    });
},

This method calls the WritePost method on the Hub. After the new post is added to the database, the Hub then calls the receivedNewPost method on all connected clients.

Clients.All.receivedNewPost(post.Id, post.Username, post.Message, post.DatePosted);

From BoardHub.cs

hub.client.receivedNewPost = function (id, username, message, date) {
    var newPost = new post(id, message, username, date);
    vm.posts.unshift(newPost);
 
    // If another user added a new post, add it to the activity summary
    if (username !== vm.username()) {
        vm.notifications.unshift(username + ' has added a new post.');
    }
};

From board.js

The Hub sends info about the new submit to this client method, which then helps make a brand new Publish JavaScript object and adds it to the starting from the view model's posts observable array. This new post is instantaneously displayed for all related customers since Knockout is observing this array. A brand new notification can also be produced for all customers other than the creator of the new publish.

Adding a remark follows the same pattern, although the client callback method differs marginally:

hub.client.receivedNewComment = function (parentPostId, commentId, message, username, date) {
    // Find the post object in the observable array of posts
    var postFilter = $.grep(vm.posts(), function (p) {
        return p.id === parentPostId;
    });
    var thisPost = postFilter[0]; //$.grep returns an array, we just want the first object
 
    var thisComment = new comment(commentId, message, username, date);
    thisPost.comments.push(thisComment);
 
    if (thisPost.username === vm.username() && thisComment.username !== vm.username()) {
        vm.notifications.unshift(username + ' has commented on your post.');
    }
};

The ID of the parent post of the comment is sent to the client, which then adds the new comment to the comments observable array of the post

Finally, let us run this point

Now you can construct and operate the project! Ooo is in dire need of a social community.

Go on and open up two browser windows and "log in" as a various person on every. Recognize how once you include a submit in a single window, it instantaneously is additional towards the other window in addition to a notification. Now, the Ice King can annoy princesses on-line too! Effectively, possibly that is not all that good.




ASP.NET SignalR Hosting - ASPHostPortal.com :: SignalR And Knockout In ASP.Net Web Pages Making use of WebMatrix

clock October 22, 2014 05:43 by author Ben

SignalR is actually a library that simplifies the creation and management of persistent connections among internet servers and clientele. This facilitates the development of programs that may screen updates to info held around the server in real-time. Chat apps will be the most evident beneficiaries of this technology, but line-of-business apps that need to report availability to customers can reward also. Listed here, I take a look at extending the canonical SignalR chat example to incorporate a "who's typing" feature, and that i also prolong my prior Knockout instance to make use of SignalR.


Very first, what is the trouble that SignalR is made to remedy? The net functions on the Request-Response design. Browsers along with other person brokers make requests and net server offer a reaction to that request.The reaction is distributed for the delivery tackle supplied within the ask for by the person agent. And that is the natural purchase of issues on the web - servers can not make responses without a request. For your most element, this is not a concern, but if you need to display real-time updates with your net webpage, you have required to vacation resort to methods like frequently polling the server making use of AJAX to determine if any modifications experienced been produced to info. Alternatively, you can use Comet engineering, which retains a persistent connection open between the server and the customer. HTML5 introduced two new techniques - Server Despatched Occasions and WebSockets. SignalR is really a user-friendly wrapper about every one of these technologies which makes it a lot much easier to develop apps that need the real-time show of knowledge. SignalR utilises HTML5 Web Sockets API where it is obtainable, and falls again onto other technologies where they may be not - Server Sent Events, Eternally Frames or Long Polling, the final two of which are Comet strategies.

SignalR is currently in pre-release - Release Prospect one to be precise. It is obtainable by way of Nuget or Github. Nevertheless, as it is pre-release, it is not obtainable by way of the WebMatrix Nuget client. But you can get it using Visible Studio (and Express For Net edition, which is free) if you pick "Include Prerelease" as an alternative of the default "Stable Only" choice. Or you can use the Package Manager Console and simply sort:

Install-Package Microsoft.AspNet.SignalR -Pre


It is suggested to set up the package by doing this (via Nuget) as you'll find quite a few bits and pieces to be set up:

The centre bit of a SignalR application is actually a hub, that is similar to a Controller in ASP.Net MVC. A hub is accountable for getting enter and creating output. Hubs are created as server-side classes that inherit from Microsoft.AspNet.SignalR.Hubs.Hub. Public methods created within a hub course are meant to be known as from consumer code. They normally outcome inside a reaction becoming despatched to the consumer. Here's the hub and technique that the Chat example in the ASP.Net internet web site features:

using Microsoft.AspNet.SignalR.Hubs;

public class ChatHub : Hub
{
    public void Send(string name, string message)
    {
        Clients.All.broadcastMessage(name, message);
    }
}


This should be saved as ChatHub.cs (a C# class file) in App_Code. A making use of directive is extra to the top in the file that makes Microsoft.AspNet.SignalR.Hubs available to the code. At runtime, a JavaScript file is produced dynamically which consists of a client-side implementation from the public Deliver technique in order that it may act as a proxy towards the server-side method. You write an implementation from the broadcastMessage approach in client-code in order that the Hub method can call it and therefore supply a reaction. You'll be able to also decide who ought to get the response through the choices obtainable:


Here's the full client-side code starting with the Layout page:

@{
    
}

<!DOCTYPE html>

<html lang="en">
    <head>
        <meta charset="utf-8" />
        <title>@Page.Title</title>
        <link href="~/Styles/site.css" rel="stylesheet" type="text/css" />
        <script src="~/Scripts/jquery-1.6.4.min.js" ></script>
        <script src="~/Scripts/jquery.signalR-1.0.0-rc1.min.js"></script>
        <script src="~/signalr/hubs"></script>
        @RenderSection("script", required: false)
    </head>
    <body>
        @RenderBody()
    </body>
</html>


Notice that there is a reference to a script called hubs in a signalr folder, neither of which exist. This is a placeholder for the dynamically generated script that translates the Hub methods to client code.

 

@{

}

    <div class="container">
        <input type="text" id="message" />
        <input type="button" id="sendmessage" value="Send" />
        <input type="hidden" id="displayname" />
        <ul id="discussion"></ul>
    </div>

@section script{
    <script type="text/javascript">
        $(function () {
 
            var chat = $.connection.chatHub;

            chat.client.broadcastMessage = function (name, message) {
                $('#discussion').append('<li><strong>' + name
                    + '</strong>:&nbsp;&nbsp;' + message + '</li>');
            };

            
            $('#displayname').val(prompt('Enter your name:', '')); 
            $('#message').focus();
            $.connection.hub.start().done(function () {
                $('#sendmessage').click(function () {
                    var encodedName = $('<div />').text($('#displayname').val()).html();
                    var encodedMsg = $('<div />').text($('#message').val()).html();
                    chat.server.send(encodedName, encodedMsg);
                    $('#message').val('').focus();
                });
            });
        });
    </script>
}

Some HTML factors are produced at the top of the file - a textual content box, button, a hidden area and an unordered checklist. Inside the script block, a client-side proxy is developed for your server-side ChatHub class:

var chat = $.connection.chatHub;

The client-side model in the hub is generated utilizing camel-case (first word lower scenario). Remember that you have to write down your personal client-side implementation of the dynamic broadcastMessage approach? The following section displays that. It requires the two strings offered from the Hub approach, and uses them to generate a list item which is additional for the unordered list. The subsequent few lines create the user by prompting to get a title which can be stored in the concealed discipline, and placing the main target within the textbox. Then the link to the hub is opened, along with a simply click function handler is additional to the button which leads to the Deliver approach inside the server edition of the hub becoming invoked:

chat.server.send(encodedName, encodedMsg);

So just to recap, the button click invokes the client-side chat.server.send method, which calls the public ChatHub.Send method, which responds with Clients.All.broadcastMessage which invokes the client-side chat.client.broadcastMessage function.

There is one final thing needed to get this working, asn that is to register the default route for hubs, which is best done in an _AppStart.cshtml file:

@using System.Web.Routing
@using Microsoft.AspNet.SignalR

@{
    RouteTable.Routes.MapHubs();
}

The chat example is easy to understand and illustrates the basic workflow nicely. But it is not a complete application by any stretch of the imagination. It needs more, and a common feature of chat applications is an indicator of who is currently typing. We can use the workflow logic above to plan an implementation.

Something on the client needs to invoke a server-side method. Keystrokes are as good an indication of typing as any, so that will do:

$('#message').keypress(function () {
    var encodedName = $('<div />').text($('#displayname').val()).html();
    chat.server.isTyping(encodedName);
});

From the definition of the client method, it should be easy to discern the name and signature of the additional method required in the ChatHub class:

public void IsTyping(string name){
    Clients.All.sayWhoIsTyping(name);
}

With each keypress, the name of the current user is passed to the server-side IsTyping method, which responds by calling a client-side function called sayWhoIsTyping:

chat.client.sayWhoIsTyping = function (name) {
    $('#isTyping').html('<em>' + name + ' is typing</em>');
    setTimeout(function () { 
        $('#isTyping').html('&nbsp;');
    }, 3000);
};

It's a rough and ready function, which takes the name passed from the server-side method, and displays it as part of a string in a div with an ID of isTyping. The text is cleared after 3 seconds.

SignalR with Knockout

I've created about Knockout prior to. In case you are undecided what Knockout is all about, you should go through the previous article first. In that prior write-up, the instance exhibits a straightforward software in which the user can choose a goods, and in the ensuing listing, choose 1 item to check out the small print. There is certainly an easy button that results within the ViewModel's unitsInStock worth reducing by one as if a obtain were created, as well as the UI being up-to-date because of this. And that is among the advantages of Knockout - adjustments to observable values inside the ViewModel result in that modify being mirrored wherever it's certain within the UI. Nevertheless the alter is localised to the personal user's browser. If a product unit is actually obtained, or indeed if more are made accessible, it might be considered a really good concept if ALL existing users are notified in the change in unitsInStock in real-time, right? Seems like a activity for SignalR.

The quantity of adjustments required for the existing Knockout sample code are actually quite tiny. I amended the existing ViewModel purchase perform and added an additional operate to manage reordering products. I also additional two computed observables (they used to be known as dependent observables); one which functions out if the consumer can purchase an item based on availability, and the other that works out if the reorder degree continues to be achieved:

viewModel.buy = function() {
    var id = this.productId();
    productsHub.server.buyProduct(id);
};

viewModel.reorder = function() {
    var quantity = this.reorderQuantity();
    var id = this.productId();
    productsHub.server.reorderProduct(quantity, id);
};

viewModel.canBuy = ko.computed(function() {
    return this.unitsInStock() > 0;
}, viewModel);

viewModel.canReorder = ko.computed(function() {
    return this.unitsInStock() <= this.reorderLevel();
}, viewModel);

I also added a reorderLevel home towards the ViewModel, and after that extra a textbox and button for reordering, and wired up its visibility for the canReorder computed observable. The reordering button and textbox will only be seen in the event the units in inventory reaches the reorder level price. The Acquire A single button is currently only enabled if you will find units in inventory. Earlier, when there were no models in stock, the end result of clicking the Buy A single was an inform indicating that no inventory existed:

<div class="row" data-bind="visible: canReorder">
    <span class="label"><input data-bind="value: reorderQuantity" class="reorder" /></span>
    <span><button data-bind="click: reorder">Reorder</button></span>
</div>
<div class="row">
    <span class="label">&nbsp;</span>
    <span><button data-bind="click: buy, enable: canBuy">Buy One</button></span>
</div>

When you have been following alongside to date, you'll be able to see that the two ViewModel features: purchase and reorder stage to server-side Hub methods that don't at present exist: BuyProduct (indicated by productsHub.server.buyProduct) and ReorderProduct (indicated by productsHub.server.reorderProduct). So listed here is the code for your ProductHub with its methods:

using Microsoft.AspNet.SignalR.Hubs;
using WebMatrix.Data;

public class ProductHub : Hub
{
    public void BuyProduct(int productId) {
        using (var db = Database.Open("Northwind")) {
            var unitsInStock = db.QueryValue("SELECT UnitsInStock FROM Products WHERE ProductId = @0",
 productId);
if (unitsInStock > 0) { db.Execute("UPDATE Products Set UnitsInStock = UnitsInStock - 1 WHERE ProductId = @0",
productId); unitsInStock -= 1; } Clients.All.updateAvailableStock(unitsInStock, productId); } }
public void ReorderProduct(int quantity, int productId){ using (var db = Database.Open("Northwind")) { db.Execute("UPDATE Products Set UnitsInStock = UnitsInStock + @0 WHERE ProductId = @1",
quantity, productId);
var unitsInStock = db.QueryValue("SELECT UnitsInStock FROM Products WHERE ProductId = @0",
productId); Clients.All.updateAvailableStock(unitsInStock, productId); } } }

This time, the adjustments brought on by user motion will likely be saved within the database, which did not occur in the prior Chat example. The BuyProduct approach retrieves the existing quantity of units in stock for the chosen product, and permits a purchase if you'll find are any. The revised quantity of units in stock, combined with the product ID are sent towards the all currently linked clientele by way of an updateAvailableStock technique. The ReorderProduct method simply raises the UnitsInStock value by whatever quantity was handed in towards the method from the ViewModel function. Once more, the revised variety of units in stock is broadcast to all related customers.

So how can the customer deal with this broadcast? It requirements an updateAvailableStock perform in order that the hub methods can get in touch with it:

productHub.client.updateAvailableStock = function(unitsInStock, productId) {
    if (viewModel.productId() == productId) {
        viewModel.unitsInStock(unitsInStock);
        $('span[data-bind="text: unitsInStock"]').effect('highlight', { color: '#9ec6e2' }, 3500);
    }
};

First is checks to see when the ID in the solution being up to date may be the 1 presently sure to the ViewModel, and when it is, the worth is updated as well as a emphasize result is used towards the span that shows the models in inventory:


ll that remains to do is to create a client-side proxy for the ProductHub and establish a connection:

productsHub = $.connection.productHub;

$.connection.hub.start();


Both of these examples are available as part of a sample site available at GitHub.

SignalR is a lot more powerful than these introductory demonstrations illustrate. You can write your own PipelineModule class and inject your own processing code into the hub pipeline. You can add authorization really easily to a hub method or a complete hub using data annotiation style attributes.



Cheap ASP.NET 4.5 Hosting

We’re a company that works differently to most. Value is what we output and help our customers achieve, not how much money we put in the bank. It’s not because we are altruistic. It’s based on an even simpler principle. "Do good things, and good things will come to you".

Success for us is something that is continually experienced, not something that is reached. For us it is all about the experience – more than the journey. Life is a continual experience. We see the Internet as being an incredible amplifier to the experience of life for all of us. It can help humanity come together to explode in knowledge exploration and discussion. It is continual enlightenment of new ideas, experiences, and passions


Author Link


 

Corporate Address (Location)

ASPHostPortal
170 W 56th Street, Suite 121
New York, NY 10019
United States

Tag cloud

Sign in