-1

I am trying to understand what would be the best approach to my problem. Let's say I have a model like this:

public class Customer
{
   [Key]
   public int Id { get; set; }
   public string Name { get; set; }
   [Required]
   public int StoreId { get; set;}
   [Required] 
   public DateTime UpdatedAt {get; set;}
}

and I have an API controller that will have a method like the following to insert a new customer in the database:

public IHttpActionResult Insert(Customer customer)
{
    customer.StoreId = 5; //just for example
    customer.UpdatedAt = DateTime.Now; //again, just as example

    if (!ModelState.IsValid)
    {
        return BadRequest(ModelState);
    }

    db.Customers.Add(customer);
    db.SaveChanges();

    return Ok(customer.Id);
}

Now as you can see in the method, let's assume the StoreId and the UpdatedAt fields won't be included in the original http request posted to this method, because those values need to be calculated and assigned at the server side (let's say basically the client is not supposed to send those values to the server side method). In this case, the ModelState won't be valid anymore, as it is missing two required fields.

One way you can get around it, is to clear the errors on the model state one by one, by doing:

 ModelState["Store.Id"].Errors.Clear();
 ModelState["UpdatedBy"].Errors.Clear();

and then doing the validation, but it doesn't look a good way especially if you have many fields that need to be taken care of on the server side.

What are the better solutions?

Behrooz
  • 1,895
  • 4
  • 31
  • 47
  • 1
    The model will be valid. If you do not pass any values for `StoreId` and `UpdatedAt` then they will be initialized as their default value (`0` and `1/1/0001`). The only way it can be invalid is if you specifically send `null` values for them. You should be using a view model that does not include those properties. And there is no point adding the `[Required]` attribute unless you want to specify a specific error message - `int` and `DateTime` are not nullable and are always required –  May 06 '16 at 00:18
  • You can set the required values or a reference value in the `view` before sending it to the controller, that way the model will always be valid. Only if you send null, it will be invalid – Polynomial Proton May 06 '16 at 00:22

1 Answers1

1

The good way ? Create a view model specific to the view and have only properties which the view is supposed to provide.

public class CustomerVm
{
   public int Id { get; set; }
   public string Name { get; set; }       
}

In your GET action, send an object of this to the view

public ActionResult Edit(int id)  //Or even Create
{
  var vm=new CustomerVm { Id=id, Name="Scott to be edited"};
  return View(vm);
}

Now your view will be strongly typed to this

@model CustomerVm
@using(Html.BeginForm())
{
  @Html.HiddenFor(s=>s.Id)
  @Html.TextBoxFor(s=>s.Name)
  <input type="submit" />
}

and in your HttpPost action, Use the same view model as your method parameter, read the property values and use that

[HttpPost]
public ActionResult Create(CustomerVm model)
{
   var customerEntity = new Customer { Name= model.Name };
   //Stuff server should set goes now
   customerEntity.StoreId = 23;
   customerEntity.UpdatedAt = DateTime.Now;

   db.Customers.Add(customerEntity);
   db.SaveChanges();
   return Ok(customerEntity.Id);
}
Shyju
  • 214,206
  • 104
  • 411
  • 497