October 5, 2012 08:13 by
Scott
In the last post, we covered the database design and the Entity model for the sample ASP.Net MVC4 Mobile application. We will continue with the Service layer in this post.
The Service Layer
We will define some methods in our service class to enter data into our SQL log tables.
- Right-click the project, select Add->New Folder and call it Services
- Right-click the Services folder, select Add, New Item and click on WCF service. Name the service
- Update the system.serviceModel section in the web.config file so that it looks like the following
< system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="customWebHttpBinding">
<security mode="None"></security>
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="JSLearning.Services.BabyMonitorServiceBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="DebugBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="JSLearning.Services.BabyMonitorService" behaviorConfiguration="DebugBehavior">
<endpoint address="" behaviorConfiguration="JSLearning.Services.BabyMonitorServiceBehavior" binding="webHttpBinding" contract="JSLearning.Services.IBabyMonitorService" bindingConfiguration="customWebHttpBinding" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
- In the Services folder, add a ServiceBase class and then copy and paste the following code to it. The ServiceBase class provides useful methods for interacting with the data Entity Model
public class ServiceBase
{
private BabyLogEntities _context = null;
private string _connectionString = string.Empty;
protected ServiceBase()
{
RenewContext();
}
protected ServiceBase(string connectionString) {
_connectionString = connectionString;
_context = new BabyLogEntities(_connectionString);
}
protected BabyLogEntities Context
{
get
{
return _context;
}
}
protected void RenewContext()
{
if (_connectionString == string.Empty)
{
_connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["BabyLogEntities"].ConnectionString;
}
_context = new BabyLogEntities(_connectionString);
return;
}
}
- Edit the BabyMonitorService.svc.cs file and have it inherit from ServiceBase.cs
public class BabyMonitorService : ServiceBase, IBabyMonitorService
- Copy and paste the following into your IBabyMonitorService.cs interface
[ServiceContract]
public interface IBabyMonitorService
{
[OperationContract]
[WebMethod]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string HeartBeat();
[OperationContract]
[WebMethod]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string AddFeedingEntry(string UserId, string FeedType, string FeedAmount);
[OperationContract]
[WebMethod]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
string AddDiaperingEntry(string UserId, string DiaperType);
}
- Here is an explanation of the public methods:
1. HeartBeat - is a simple contract to verify that the service is responding
2. AddFeedingEntry - is used to make an entry for a feeding session
3. AddDiaperingEntry - is used to make an entry for a diaper change
- Open the BabyMonitorService.svc.cs file and add the following code:
public class BabyMonitorService : ServiceBase, IBabyMonitorService
{
public BabyMonitorService() : base()
{ }
/// <summary>
/// Check that the service is available
/// </summary>
/// <returns></returns>
public string HeartBeat()
{
return "Service is alive";
}
/// <summary>
/// Add a feed entry
/// </summary>
/// <param name="UserId"></param>
/// <param name="FeedType"></param>
/// <param name="FeedAmount"></param>
/// <returns></returns>
public string AddFeedingEntry(string UserId, string FeedType, string FeedAmount)
{
Models.WebServiceResponse response = new Models.WebServiceResponse();
try
{
var log = new FeedingLog
{
ID = Guid.NewGuid(),
DateCreated = DateTime.Now,
FeedType = FeedType,
// since IIS does not like the . character, we are passing decimals as x_y and converting to x.y
FeedAmount = Decimal.Parse(FeedAmount.Replace("_", ".")),
UserID = UserId
};
RenewContext();
Context.AddToFeedingLogs(log);
Context.SaveChanges();
response.IsSuccess = true;
}
catch (Exception ex)
{
response.IsSuccess = false;
response.ErrorMessage = ex.Message;
}
return SerializeAsJSON(response);
}
/// <summary>
/// Add an entry for a diaper change
/// </summary>
/// <param name="UserId"></param>
/// <param name="DiaperType"></param>
/// <returns></returns>
public string AddDiaperingEntry(string UserId, string DiaperType)
{
Models.WebServiceResponse response = new
Models.WebServiceResponse();
try
{
var log = new DiaperLog
{
ID = Guid.NewGuid(),
DateCreated = DateTime.Now,
DiaperType = DiaperType,
UserID = UserId
};
RenewContext();
Context.AddToDiaperLogs(log);
Context.SaveChanges();
response.IsSuccess = true;
}
catch (Exception ex)
{
response.IsSuccess = false;
response.ErrorMessage = ex.Message;
}
return SerializeAsJSON(response);
}
/// <summary>
/// Serializes an object to JSON
/// </summary>
/// <param name="response"></param>
/// <returns></returns>
private string SerializeAsJSON(Models.WebServiceResponse response)
{
using (MemoryStream s = new MemoryStream())
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(Models.WebServiceResponse));
ser.WriteObject(s, response);
s.Position = 0;
using (StreamReader sr = new StreamReader(s))
{
return sr.ReadToEnd();
}
}
}
}
- The code is quite simple, it uses the Entity Model to make an entry into the respective tables and returns the WebServiceResponse object in JSON format.
- In the Models folder, add a class called WebServiceResponse and add the following code. The WebServiceResponse is a nice way to return an object as the JSON response, and it can contain a lot of details from the service rather than a simple string error message. Check the service class to see how this object is built.
[DataContract]
public class WebServiceResponse
{
/// <summary>
/// Indicates if the web service call was successful
/// </summary>
[DataMember]
public bool IsSuccess = false;
/// <summary>
/// Contains the response message from the service
/// </summary>
[DataMember]
public object Payload = "Object not assigned";
/// <summary>
/// Contains a friendly error message if the service encountered an exception
/// </summary>
[DataMember]
public string FriendlyErrorMessage = string.Empty;
/// <summary>
/// Contains the full text of the exception, if one occurred
/// </summary>
[DataMember]
public string ErrorMessage = string.Empty;
/// <summary>
/// Contains the exception trace, if one occurred
/// </summary>
[DataMember]
public string ErrorStackTrace = string.Empty;
/// <summary>
/// Contains the date and time of the service response in UTC format.
/// </summary>
[DataMember]
public string UTC_DateOfResponse = DateTime.Now.ToUniversalTime().ToString("dd MMM yyyy hh:mm:ss tt");
}
- At this point we should be able to compile the project and browse to the service. Go to http://yoursite/Services/BabyMonitorService.svc
- You can also invoke the HeartBeat method from earlier to see if your service is working correctly. Note, you will need to save the JSON response and then open it in notepad to see the results