There are many tutorials that focus on one or two technologies involved in creating an interactive web application, but none cover all the elements of creating a complete solution that uses Entity Framework, MVC, Knockout, Ajax, jQuery validation, and concurrency tracking to roundtrip from client to server and back again. This training course teaches in a way you can easily understand and then apply these elements to your own projects.
There are many tutorials that focus on one or two technologies involved in creating an interactive web application, but none cover all the elements of creating a complete solution that uses Entity Framework, MVC, Knockout, Ajax, jQuery validation, and concurrency tracking to roundtrip from client to server and back again. Even those that partially cover the technologies involved still do not cover the complexities of handling parent-child data models, such as sales orders and their associated line items. This training course teaches in a way you can easily understand and then apply these elements to your own projects.
Adam Churvis is a software developer and quality assurance specialist with over twenty-five years of software industry experience. He is the President of Productivity Enhancement, a consulting, development, and testing firm. He works throughout the Microsoft stack but follows cool tech wherever it shows up, especially in robotics. Adam has co-authored three books on computer technology and has spoken at user groups throughout the United States.
Adding a Single Entity Now that you're comfortable wiring things up enough to display a Single Entity, let's go a little further and create one. For this, we need to create a client-side Save function that sends the client-side ViewModel to the server, and a corrsponding server-side save controller action to take that ViewModel data, create a SalesOrder entity out of it, and hand it off to Entity Framework, which will handle the persistence layer. As with the rest of this lesson, we're going to build this functionality in layers, so you won't get overloaded with too many things to remember.
Editing a Single Entity The goal of this module is to create a mechanism that instructs Entity Framework what to do with the data we send it, so that the application can distinguish adds from updates. This mechanism will be triggered by user actions in the client, and then, reset after Entity Framework does what it needs to do, so that the data sent back to the client can start from scratch after each time the Save button is clicked.
Deleting a Single Entity Deleting works through the same Save client-side function and Save controller action as does creating and editing, but we don't return a ViewModel to the View, because, well, there's no ViewModel to return. Instead, we'll redirect back to the list of sales orders after deleting one of them. This is where we adapt the contents of the anonymous JSON object we returned from the Save controller action, to include the URL to which we want to redirect, and then handle the redirect in the client.
Refactoring for Easier Development I've repeated myself a number of times in this course as a way to iterate a concept to make it more familiar, but now it's time to incorporate a little "don't repeat yourself" and refactor a few things. This will remove a good bit of bulk from the places where we're writing code and generally make development easier. Also, after this module, we'll start adding related child entities so the views are going to get busy. I hate working with ugly views, so we'll top off this module by prettying things up a bit using Bootstrap.
Adding Children It's a good thing that we've spent time getting the basics under our belt because we don't want to be learning that along with all the moving parts we're about to encounter, so if there's anything at all you're not yet comfortable with, go back and rehearse it until you are before proceeding. It's unfortunate that handling something as commonplace as data models with parent-child relationships is not more easily implemented across the technology stack. When I first started putting all these pieces together and honing a complete solution, I couldn't believe it would be so involved and have such a lack of documentation or tutorials, but once you get to the end of this course, if you've been coding along with me, you'll see that it all makes perfect sense and you'll have an easily repeatable pattern to follow for all your MVC apps. Okay, so here's what we're going to do so that we can add children, which in our case are sales order items. First, we'll define and configure the sales order item model and update the database to support it. Second, we'll define the server-side sales order item view model and make provisions for our collection of them in the sales order view model. Third, we'll define the client-side sales order item view model and configure knockout mapping to create one each time it encounters the sales order item in the data. Fourth, we'll create a Knockout template in the partial views to present the sales order items to the user. And finally, we'll learn how to handle identity keys for a collection of new sales order items.
Editing Children Thankfully, implementing the ability to edit child entities is very simple. We flag the child as edited, send it to the save function in the client to the save controller action we already have in place, and it works perfectly. It won't take us much time to implement child editing so I'm going to take a little time to show you how to implement computed observables, which automatically update their computed values whenever client-side view model data changes. For example, it's a good idea to display the extended price for each item, which is the product of quantity times unit price. Any time the user enters a new value for either quantity or user price, the value of extended price will automatically recalculate. This is exactly what computed observables are for.
Deleting Children So far, adding and editing child entities have been relatively straightforward, but deleting child entities are a whole different story. Consider retrieving a sales order and deleting one of its sales order items. When you click save and send the data to the server, the server has no idea you've deleted a sales order item because this is a web application and Entity Framework is disconnected from the source between requests. The only way to handle this effectively is to create on the client a collection of the keys of those children that were deleted, send them to the server, and iterate through the context setting ObjectState to deleted.
Client-Side Validation I'm going to cover the three types of client-side validation you're likely to come across. HTML5 validation, unobtrusive validation, and jQuery validation. You'll learn the pros and cons of each one, but we'll concentrate mostly on jQuery validation because it's the one we'll implement in the finished application.
Server-Side Validation Client-side validation is never enough. Data inputs must be validated in the client to prevent bad data from being presented to the application layer and then in the application layer, the data must be validated again to prevent bad data from being presented to the data layer. Why validate in the client when it's going to be validated on the server anyway? Preventing unnecessary submissions to the server is always a good thing. Do as much as you can on the client and you will relieve the server of the burden. On the other hand, there are things that server-side validation can do that client-side validation cannot, such as validate using business logic that is backed by server resident data, or that uses complicated proprietary logic that would be either impractical or legally impermissible to expose in browsers. So if you have a dynamic set of complex business rules that must all pass for validation to pass, this sort of validation is not even considered by the client and instead processed entirely on the server. We're going to layer in server-side validation to match client-side validation, plus we'll add a business rule to the server-side validation and show how to handle it.
Handling Concurrency All too often I've seen developers design and construct business systems as if they were single-user applications and then wonder why there were so many deadlocks and overwritten data when the app is deployed. It's because concurrency was not considered was not considered at all points during the design and engineering of the system. Concurrency is not an add-on. You can't design and build a working application and then suddenly decide to make it multi-user. There are two major areas to consider with concurrency. First, the application level mechanism that will be aware of changes made to data by other users, and second, the physical database level features and configurations designed to accommodate high-load concurrency transactions. While the second item, which consists of database modeling, index design, transactional isolation and query execution plan analysis are critical in creating solid multi-user systems, it's an entire discipline way beyond the scope of this course so we'll concentrate on the application-level mechanism, which is handled entirely by Entity Framework and is well within our scope. One thing before we start. Now that you know that validation works, I'm going to change the seed method to create sales order items with the valid product codes. I'm going to just delete the existing database and then recreate it by calling update database again. There. Everything works.