Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

Part 16 - Difference between updatemodel and tryupdatemodel

Suggested Videos 
Part 13 - FormCollection in mvc
Part 14 - Mapping asp.net request data to controller action simple parameter types
Part 15 - Updatemodel function in MVC



In this video we will discuss the differences between updatemodel and tryupdatemodel functions. Please watch Part 15, before proceeding.



Make changes to "Create_Post()" controller action method as shown below.
[HttpPost]
[ActionName("Create")]
public ActionResult Create_Post()
{
    EmployeeBusinessLayer employeeBusinessLayer =
        new EmployeeBusinessLayer();

    Employee employee = new Employee();
    UpdateModel(employee);
    if (ModelState.IsValid)
    {
        employeeBusinessLayer.AddEmmployee(employee);
        return RedirectToAction("Index");
    }
    else
    {
        return View();
    }
}

Please note that, "AddEmmployee()" method is now inside the "IF" condition that checks the validity of ModelState using ModelState.IsValid boolean property. Run the application and navigate to the following URL.
http://localhost/MVCDemo/Employee/Create

Submit the page without entering any data. You will get an error stating - "The model of type 'BusinessLayer.Employee' could not be updated". This is because "DateOfBirth" property of "Employee" class is a non-nullable DateTime data type. DateTime is a value type, and needs to have value when we post the form. To make "DateOfBirth" optional change the data type to nullable DateTime as shown below.
public class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Gender { get; set; }
    public string City { get; set; }
    public DateTime? DateOfBirth { get; set; }
}

Run the application and navigate to the following URL.
http://localhost/MVCDemo/Employee/Create

Submit the page without entering any data. You will now get a different error stating - Procedure or function 'spAddEmployee' expects parameter '@Name', which was not supplied.

This is because, the following parameters of stored procedure "spAddEmployee" are all required.
@Name
@Gender
@City
@DateOfBirth

To make all these parameters optional, modify the stored procedure as shown below.
Alter procedure spAddEmployee    
@Name nvarchar(50) = null,    
@Gender nvarchar(10) = null,     
@City nvarchar (50) = null,     
@DateOfBirth DateTime  = null  
as    
Begin    
 Insert into tblEmployee (Name, Gender, City, DateOfBirth)    
 Values (@Name, @Gender, @City, @DateOfBirth)    
End

Run the application and navigate to the following URL.
http://localhost/MVCDemo/Employee/Create

Submit the page without entering any data. You will now get a different error stating - Object cannot be cast from DBNull to other types.

To fix this error, make changes to "Employees" property in "EmployeeBusinessLayer.cs" file as shown below. Notice that we are populating "DateOfBirth" property of "Employee" object only if "DateOfBirth" column value is not "DBNull".
public IEnumerable<Employee> Employees
{
    get
    {
        string connectionString =
            ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;

        List<Employee> employees = new List<Employee>();

        using (SqlConnection con = new SqlConnection(connectionString))
        {
            SqlCommand cmd = new SqlCommand("spGetAllEmployees", con);
            cmd.CommandType = CommandType.StoredProcedure;
            con.Open();
            SqlDataReader rdr = cmd.ExecuteReader();
            while (rdr.Read())
            {
                Employee employee = new Employee();
                employee.ID = Convert.ToInt32(rdr["Id"]);
                employee.Name = rdr["Name"].ToString();
                employee.Gender = rdr["Gender"].ToString();
                employee.City = rdr["City"].ToString();
                if (!(rdr["DateOfBirth"] is DBNull))
                {
                    employee.DateOfBirth = Convert.ToDateTime(rdr["DateOfBirth"]);
                }

                employees.Add(employee);
            }
        }

        return employees;
    }
}

Run the application and navigate to the following URL
http://localhost/MVCDemo/Employee/Create

Submit the page without entering any data. Notice that a blank employee row is inserted into tblEmployee table.

Now let's make the following properties of "Employee" class required.
Name
City
DateOfBirth

To achieve this we can use "Required" attribute that is present in System.ComponentModel.DataAnnotations namespace. To use this namespace, BusinessLayer project need a reference to "EntityFramework" assembly. The changes to the "Employee" class are shown below.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel.DataAnnotations;

namespace BusinessLayer
{
    public class Employee
    {
        public int ID { get; set; }
        [Required]
        public string Name { get; set; }
        public string Gender { get; set; }
        [Required]
        public string City { get; set; }
        [Required]
        public DateTime? DateOfBirth { get; set; }
    }
}

Run the application and navigate to the following URL.
http://localhost/MVCDemo/Employee/Create

Submit the page without entering any data. We now get an error stating - The model of type 'BusinessLayer.Employee' could not be updated. Notice that this error is thrown when UpdateModel() function is invoked.

Now let's use TryUpdateModel() instead of UpdateModel(). Make changes to "Create_Post()" controller action method in "EmployeeController" as shown below.
[HttpPost]
[ActionName("Create")]
public ActionResult Create_Post()
{
    EmployeeBusinessLayer employeeBusinessLayer =
        new EmployeeBusinessLayer();

    Employee employee = new Employee();
    TryUpdateModel(employee);
    if (ModelState.IsValid)
    {
        employeeBusinessLayer.AddEmmployee(employee);
        return RedirectToAction("Index");
    }
    else
    {
        return View();
    }
}

Run the application and navigate to the following URL
http://localhost/MVCDemo/Employee/Create

Submit the page without entering any data. Notice that, we don't get an exception now and the user remains on "Create" view and the validation errors are displayed to the user.

So, the difference is UpdateModel() throws an exception if validation fails, where as TryUpdateModel() will never throw an exception. The similarity is, both the functions are used to update the Model with the Form values and perform the validations.

Is it mandatory to use "UpdateModel()" or "Try"UpdateModel()" function to update the Model?
The answer is NO.

The above method can be re-written as shown below and we get the same behaviour.
[HttpPost]
[ActionName("Create")]
public ActionResult Create_Post(Employee employee)
{
    EmployeeBusinessLayer employeeBusinessLayer =
        new EmployeeBusinessLayer();

    if (ModelState.IsValid)
    {
        employeeBusinessLayer.AddEmmployee(employee);
        return RedirectToAction("Index");
    }
    else
    {
        return View();
    }
}

So the next question is, Why do we need to explicitly invoke model binding?
If you want to limit on what can be bound, explicitly invoking model binding can be very useful. We will discuss more about this in a later video session.

10 comments:

  1. Hi Venkat,

    you loose [Required] on Gender

    Regards
    Luca Jonathan Panetta

    ReplyDelete
  2. Hello Sir
    I used required attribute on gender property but it didn't show validation message why?

    ReplyDelete
    Replies
    1. I am using aspx engine it is working properly but it does not display validation msg.

      Delete
    2. its working for me.check it once you are missing something.

      Delete
  3. Hi mahesh bisht!
    I think you try to see HTML code generated:

    /*****************/
    select id="Gender" name="Gender"
    option value="" Select Gender /option
    option value="Male" Male /option
    option value="Female" Female /option
    /select
    /*****************/

    Sorry because I don't know write tag HTML in this comment :)

    Here default value of Gender is "" - if user no choice(Select Gender).
    Hope help for you :)

    ReplyDelete
  4. Thank you Eng Venkat.
    Is there another way instead of all the time writing inter connect to the database and then open the connection to the database.

    ReplyDelete
  5. even my Required[] attributes are not working can some one help me out

    ReplyDelete
    Replies
    1. Hello ranjith,

      Add System.ComponentModel.DataAnnotations through references in your BusinessLayer project and Include in class using System.ComponentModel.DataAnnotations;
      see its works?

      Delete
  6. @{
    List listgender = new List();
    listgender.Add(new SelectListItem
    {
    Text = "Male",
    Value = "Male"
    });
    listgender.Add(new SelectListItem
    {
    Text = "Female",
    Value = "Female",

    });

    }

    @Html.DropDownListFor(model => model.REGGender, listgender, "Gender", new { @class = "form-control" })
    @Html.ValidationMessageFor(model => model.REGGender)

    ReplyDelete
  7. Very deep explanation sir, Thank you verh much for such a wonderful series of ASP.Net MVC

    ReplyDelete

It would be great if you can help share these free resources