Continuing from our discussion around a sample ASP.Net MVC4 Mobile application, this final post will discuss the final piece; the UI and how it all comes together.
Update: I forgot to include the SQL scripts for the database, as pointed out by @Anonymous. So download this script, create a new database and run it. Do not forget to update your SQL connection string in the MVC application!
The User Interface
The default project uses the jQuery mobile plugin to target mobile devices. The jQuery mobile plugin is touch-optimized for smartphones and tablets and it targets iOS, Android, Blackberry, Bada, Windows Phone, Palm WebOS, Symbian and MeeGo.
Lets start with the JavaScript logic, which will perform the interaction between the HTML UI and the JSON web service.
- In the Scripts folder, add a folder called com then sukul underneath that and finally babyfeeding underneath that
- In the final babyfeeding folder, add a JavaScript file and called it proxy.js
- Copy and paste the following code into the js file
if (Sukul == undefined) var Sukul; if (!Sukul) Sukul = {}; //Constructor Sukul.Proxy = function (siteBaseUrl) { // constructor Sukul.Proxy.prototype.baseUrl = siteBaseUrl; Sukul.Proxy.prototype.heartBeatUrl = siteBaseUrl + "/Services/BabyMonitorService.svc/HeartBeat"; Sukul.Proxy.prototype.FeeedingUrl = siteBaseUrl + "/Services/BabyMonitorService.svc/AddFeedingEntry" Sukul.Proxy.prototype.DiaperingUrl = siteBaseUrl + "/Services/BabyMonitorService.svc/AddDiaperingEntry" } Sukul.Proxy.prototype = { CallWebService: function (url, input, successCallBack, errorCallBack) { //Uncomment the next line to support JSONP //url = url + "?callback=?"; $.ajax({ async: false, cache: false, type: "GET", contentType: "application/json; charset=utf-8", url: url, dataType: "json", data: input, success: successCallBack, error: errorCallBack }); }, HeartBeat: function (successFunction, failFunction) { this.CallWebService(this.heartBeatUrl, "", successFunction, failFunction); }, AddFeeding: function (UserId, FeedType, FeedAmount, successFunction, failFunction) { var input = "UserId=" + UserId + "&FeedType=" + FeedType + "&FeedAmount=" + FeedAmount; this.CallWebService(this.FeeedingUrl, input, successFunction, failFunction); }, AddDiapering: function (UserId, DiaperType, successFunction, failFunction) { var input = "UserId=" + UserId + "&DiaperType=" + DiaperType; this.CallWebService(this.DiaperingUrl, input, successFunction, failFunction); } };
- The JavaScript is structured using objects and namespaces. Every JavaScript object contains an inner class called Prototype. By defining methods on this inner class, we can encapsulate object variables and methods and share them across concrete instances of the class. In the code above, the Proxy object defines the following methods:
- CallWebService - helper method for invoking the JSON service
- HearBeat - invokes the Heat method call for diagnostics
- AddFeeding - creates a feed entry by taking input from the form and invoking the web service
- AddDiapering - creates an entry for a diaper change by taking input from the form and invoking the web service
- Finally, we encapsulate the Proxy object inside the Sukul object to create a namespace so that the proxy object can be referenced like so: Sukul.Proxy
The Index.cshtml View
Copy and paste the following code for the Index page
@{
ViewBag.Title = "Baby Log Home";
}
<script type="text/javascript">
$(document).ready(function () {
$("#btnSubmit").click(function () {
$("#txtLastEntry").val("Last: ");
// Create the proxt class
var proxy = new Sukul.Proxy("@Request.Url.GetLeftPart(UriPartial.Authority)");
// Add the feeding entry
if ($("#chkFeed").attr("checked") != undefined && $("#chkFeed").attr("checked") == "checked") {
proxy.AddFeeding("@Membership.GetUser().UserName", $("#drpType").val(), $("#drpAmount").val(),
function (result) {
// succeeded
$("#txtLastEntry").val($("#txtLastEntry").val() + $("#drpAmount option:selected").text() +
" of " + $("#drpType option:selected").text());
},
function (jqXHR, textStatus, errorThrown) {
// failed
var err = "Details: " + textStatus;
if (errorThrown != undefined) {
err += "\rMore details : " + errorThrown;
}
alert(err);
});
}
// Add the diapering entry
if ($("#chkDiaper").attr("checked") != undefined && $("#chkDiaper").attr("checked") == "checked") {
proxy.AddDiapering("@Membership.GetUser().UserName", $("#drpDiaper").val(),
function (result) {
// succeeded
$("#txtLastEntry").val($("#txtLastEntry").val() + ", " +
$("#drpDiaper option:selected").text() + " diaper");
},
function (jqXHR, textStatus, errorThrown) {
// failed
var err = "Details: " + textStatus;
if (errorThrown != undefined) {
err += "\rMore details : " + errorThrown;
}
alert(err);
});
}
});
});
</script>
<div data-role="fieldcontain" data-inset="true">
<fieldset data-role="controlgroup">
<legend>Feed Details</legend>
<input id='chkFeed' name='chkFeed-1' type="checkbox" checked="checked" class="custom" />
<label for="chkFeed">
Log Feed</label>
</fieldset>
<fieldset data-role="controlgroup">
<legend>Feed Type:</legend>
@Html.DropDownList("drpType", new List<SelectListItem> {
new SelectListItem { Text="Bottle", Value="Bottle", Selected=true },
new SelectListItem { Text="Left", Value="Left" },
new SelectListItem { Text="Right", Value="Right" },
})
</fieldset>
<fieldset data-role="controlgroup">
<legend>Amount:</legend>
@Html.DropDownList("drpAmount", new List<SelectListItem> {
new SelectListItem { Text="0.5 oz.", Value="0_5" },
new SelectListItem { Text="1.0 oz.", Value="1_0" },
new SelectListItem { Text="1.5 oz.", Value="1_5" },
new SelectListItem { Text="2.0 oz.", Value="2_0" },
new SelectListItem { Text="2.5 oz.", Value="2_5", Selected=true },
new SelectListItem { Text="3.0 oz.", Value="3_0" },
new SelectListItem { Text="3.5 oz.", Value="3_5" },
new SelectListItem { Text="4.0 oz.", Value="4_0" },
new SelectListItem { Text="4.5 oz.", Value="4_5" },
new SelectListItem { Text="5.0 oz.", Value="5_0" },
new SelectListItem { Text="5.5 oz.", Value="5_5" },
new SelectListItem { Text="6.0 oz.", Value="6_0" },
new SelectListItem { Text="6.5 oz.", Value="6_5" },
new SelectListItem { Text="7.0 oz.", Value="7_0" },
new SelectListItem { Text="7.5 oz.", Value="7_5" },
new SelectListItem { Text="8.0 oz.", Value="8_0" },
new SelectListItem { Text="8.5 oz.", Value="8_5" },
new SelectListItem { Text="9.0 oz.", Value="9_0" }
})
</fieldset>
</div>
<div data-role="fieldcontain" data-inset="true">
<fieldset data-role="controlgroup">
<legend>Diaper Details</legend>
<input id='chkDiaper' name='chkDiaper-1' type="checkbox" class="custom" />
<label for="chkDiaper">
Log Diaper</label>
</fieldset>
<fieldset data-role="controlgroup">
<legend>Diaper:</legend>
@Html.DropDownList("drpDiaper", new List<SelectListItem> {
new SelectListItem { Text="Wet", Value="wet", Selected=true },
new SelectListItem { Text="Dirty", Value="dirty" },
new SelectListItem { Text="Both", Value="both" }
})
</fieldset>
</div>
<div data-role="fieldcontain" data-inset="true">
<input id="btnSubmit" type="submit" value="Submit" data-role="button" />
<fieldset data-role="controlgroup">
<input id="txtLastEntry" readonly="readonly" type="text" />
</fieldset>
</div>
The HTML code builds the input form for entering the feed and diaper change details and the Javascript code collects the input, creates the proxy class and calls its methods to invoke the web service.
Notice how the @ tag is used to inject runtime variables, such as the logged on user and the base url.


I am working through your tutorial.
ReplyDeleteUsing download.
Application run failed with:
Message=The connection name 'LocalSqlServer' was not found in the applications configuration or the connection string is empty.
I suspect something to do with the database setup.
Upgraded all js packages, ran again, same error.
Detailed Exception:
System.Configuration.ConfigurationErrorsException was unhandled by user code
Message=The connection name 'LocalSqlServer' was not found in the applications configuration or the connection string is empty. (C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config line 238)
Source=System.Web
BareMessage=The connection name 'LocalSqlServer' was not found in the applications configuration or the connection string is empty.
Filename=C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config\machine.config
Line=238
StackTrace:
at System.Web.Configuration.ProvidersHelper.InstantiateProvider(ProviderSettings providerSettings, Type providerType)
at System.Web.Configuration.ProvidersHelper.InstantiateProviders(ProviderSettingsCollection configProviders, ProviderCollection providers, Type providerType)
at System.Web.Security.Membership.InitializeSettings(Boolean initializeGeneralSettings, RuntimeConfig appConfig, MembershipSection settings)
at System.Web.Security.Membership.Initialize()
at System.Web.Security.Membership.get_Provider()
at System.Web.Security.Membership.ValidateUser(String username, String password)
at JSLearning.Controllers.AccountController.LogOn(LogOnModel model, String returnUrl) in C:\Users\Peter\Downloads\JSLearning.Mobile\JSLearning\Controllers\AccountController.cs:line 42
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass15.b__12()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
InnerException: System.Configuration.Provider.ProviderException
Message=The connection name 'LocalSqlServer' was not found in the applications configuration or the connection string is empty.
Source=System.Web
StackTrace:
at System.Web.Util.SecUtility.GetConnectionString(NameValueCollection config)
at System.Web.Security.SqlMembershipProvider.Initialize(String name, NameValueCollection config)
at System.Web.Configuration.ProvidersHelper.InstantiateProvider(ProviderSettings providerSettings, Type providerType)
InnerException:
Thanks for the catch. Post updated.
Delete