©
[1/13] Become a Full-stack .NET Developer: Implementing a Use Case from Top to Bottom

[1/13] Become a Full-stack .NET Developer: Implementing a Use Case from Top to Bottom

This module involved the implementation of one of our primary use cases to allow a user to attend a certain gig by adding that gig to their calendar. We needed to do a bit of class modelling before starting on coding this.

The domain model for a user adding a gig to their calendar, establsining a many-to-many relationship.

The domain model for a user adding a gig to their calendar, establsining a many-to-many relationship.

The requirements document stipulated that a user must be able to add a gig to their calendar and on a separate page view the gigs they are attending. So a user can attend many gigs, and a gig can have many users. With this many-to-many relationship established, there will be no need for an extraneous classes such as Calendar, Month or Day (only useful if integrating with a third party calendar system such as iCal, which is outside the scope of the requirements document).

The relational model for a user adding a gig to their calendar, with a intermediate Attendance class for making LINQ queries between the two classes.

The relational model for a user adding a gig to their calendar, with a intermediate Attendance class for making LINQ queries between the two classes.

When we take this object model and transpose it into a relational database model we need to add a intermediate table called Attendance, for our many-to-many relationships. Thankfully, Entity Framework can create this table for us as part of a migration.

We then decided to add this Attendance class from our relationship model back into our domain model. The reasoning for this being, that at some point we will want to query that object directly (using LINQ), such as user deleting a gig from their calendar, or checking that gig has not already been added to a user's calendar.

We extended our domain model to include this new Attendance class by adding it into our Models folder. The following code was then inserted into this Attendance class.

namespace GigHub.Models
{
  public class Attendance
    {
      public Gig Gig { get; set; }
      public ApplicationUser Attendee { get; set; }
  
      [Key]
      [Column(Order = 1)]
      public int GigId { get; set;}
  
      [Key]
      [Column(Order = 2)]
      public string AttendeeId { get; set;}
    }
}

In this code we add the properties for the Gig and User (Attendee) to our model. For the corresponding ID properties for these properties we also needed to add the Key and Column data annotations to map these to a database table as the combination of a GigId and a AttendeeId uniquely represents a Gig attendance.

As we will be querying a Attendance object directly, we needed to add a DbSet to our DbContext in the ApplicationDbContext file.

With this out of the way, we performed a migration in the Package Manager Console under the name of "AddAttendance". Reviewing the migration we noted that the primary key of this new Attendance table was the combination of GigId and AttendeeId. When we then attempted to run this migration on our database, we encountered an error. This error was caused by having multiple cascade paths in our model when a user goes to a delete a Gig attendance. To rectify this issue we would need to implement Fluent API into our solution.

In order to use Fluent API we need to override the onModelCreating() method in the ApplciationDbContext file. Here was the resulting code.

protected override void onModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<Attendance>.HasRequired(a => a.Gig).WithMany().WillCascadeOnDelete(false);
  base.onModelCreating(modelBuilder);
}

This code overrides the code first conventions of our domain model and turns off cascade delete for our attendance records. Our migration to the database was now successful as a result.

With this out of the way we turned our attention to producing a lightweight RESTful API to implement Jquery AJAX on the frontend of our app. This would allow for users to click a button to attend a gig without having to reload the current page. This API will be exposed as a endpoint on api/attendances/ using HTTP POST. The data to be exchanged will include the gigID and the currently logged in user's ID. For security reasons, this API should perform user authentication on the server and restrict it to only authenticated users.

To create this API, we added a new Web API controller named AttendancesController to our Controller folder in Solution Explorer. Visual Studio then informed us that we needed to add a new line to our Global.ASAX file in the Application_Start() method.

GlobalConfiguration.Configure(WebAPIConfig.Register)

In our new API controller, we created an action called Attend that takes a parameter called gigID and the currently logged in user's ID.

[HTTPPOST]
public IHTTPActionResult Attend ([FromBody] int gigId)
{
  var attendance = new Attendance
  {
    GigId = gigId;
    AttendeeId = User.Identity.GetUserId();
  };
  _context.Attendances.Add(attendance);
  _context.SaveChanges();
  
  return OK();
}
What our app looks like at the end of this module, with a Attendance button now added to our gig lsitings.

What our app looks like at the end of this module, with a Attendance button now added to our gig lsitings.

Now we will need to test our new WEB API. In order to do this testing we will use the Postman Chrome plugin. Within the Postman interface we entered the URL for our newly created API, which in our case was located at http://localhost:50299/api/attendances/. We requested a POST method to be returned from this API in RAW output. We also needed to ensure we were logged into our Gighub app in our browser to receive the proper API response.

After verifying our WEB API to keep track of gig attendances was working as intended, we now needed to implement a simple button in our UI for users to Attend a Gig. In our Views folder, we edited Index.CSHTML underneath our existing Razor view to include a new Bootstrap button entitled "Going?". we also needed to fiddle around a little bit with our CSS to get this newly added button to properly align with the existing form content. 

To wire our "Going?" button up to our Attendances Web API, we needed to add a bit of Javascript to our view. This code would also change the label on our button from "Going?" to simply "Going" after a user clicks on it.

$(document).ready(function()
  {
  $(".js-toggle-attendance").click(function(e)
  var button = $(e.target);
    {
        $.post("/api/attendances", button.attr("data-gig-id"))
        .done(function(){
        button.removeClass("btn-default").addClass("btn-info").text("Going")
        })
    };
   };

With our button now correctly wired up to WEB API, we now came to an end to this particular module as we had successfully completely the use case of gig attendance from top to bottom. One other takeaway from this module, was that for each of the steps  we focused only on that aspect of development and did'nt get too bogged down in other use-cases(that we will tackle in due time).

Blog Categories - Technology · Personal

[1/14] Become a Full-stack .NET Developer: Implementing Secondary Use Cases

[1/14] Become a Full-stack .NET Developer: Implementing Secondary Use Cases

[1/7] Become a Full Stack .NET Developer: Implementing Validation

[1/7] Become a Full Stack .NET Developer: Implementing Validation