Reputation: 65
I would like to ask is there any way to set an automatic DateTime.Now
value for properties ENTRY_DATE
and AUDIT_TIME
in the Create()
HttpPost method? The form is created and it works fine. If the DateTime is inserted manually. But, it won't work if I set an automatic value and would run into a
"One or more validation Error's"..
This is my model (I don't understand how to make a viewmodel) :
public partial class TRRESPONDENT
{
public TRRESPONDENT()
{
this.TRFOLLOWUPRESPONDENTs = new HashSet<TRFOLLOWUPRESPONDENT>();
}
[Required(ErrorMessage = "Respondent ID is required!")]
[Display(Name = "Respondent ID")]
public string RESPONDENT_ID { get; set; }
[Required(ErrorMessage = "Please select a BINUS Center!")]
[Display(Name = "Binus Center")]
public string BC_ID { get; set; }
[Required(ErrorMessage = "Name cannot be empty!")]
[Display(Name = "Name")]
[StringLength(100,ErrorMessage = "Name length cannot be more than 100 characters!")]
public string FULL_NAME { get; set; }
.... // more properties
[Required(ErrorMessage = "Please pick a City Location!")]
[Display(Name = "City")]
public int CITY_ID { get; set; }
// The following 2 properties need to be set
[Display(Name = "Entry Date")]
public DateTime ENTRY_DATE { get; set; }
public DateTime AUDIT_TIME { get; set; }
....
public virtual LTCITY LTCITY { get; set; }
public virtual LTSOURCERESPONDENT LTSOURCERESPONDENT { get; set; }
public virtual MSBINUSCENTER MSBINUSCENTER { get; set; }
public virtual ICollection<TRFOLLOWUPRESPONDENT> TRFOLLOWUPRESPONDENTs { get; set; }
}
This is my view
@using (Html.BeginForm())
{
@Html.AntiForgeryToken()
@Html.LabelFor(model => model.RESPONDENT_ID)
@Html.EditorFor(model => model.RESPONDENT_ID)
@Html.ValidationMessageFor(model => model.RESPONDENT_ID)
@Html.LabelFor(model => model.BC_ID, "Binus Center")
@Html.DropDownList("BC_ID", null)
@Html.ValidationMessageFor(model => model.BC_ID)
@Html.LabelFor(model => model.FULL_NAME)
@Html.EditorFor(model => model.FULL_NAME)
@Html.ValidationMessageFor(model => model.FULL_NAME)
.... // more form controls
@Html.LabelFor(model => model.CITY_ID, "City")
@Html.DropDownList("CITY_ID", null)
@Html.ValidationMessageFor(model => model.CITY_ID)
@Html.HiddenFor(model => model.ENTRY_DATE)
@Html.HiddenFor(model => model.AUDIT_TIME)
<input type="submit" value="Create" class="btn btn-default" />
}
This is my controller :
public class RespondentController : Controller
{
private RespondentBINUSEntities db = new RespondentBINUSEntities();
public ActionResult Create()
{
ViewBag.CITY_ID = new SelectList(db.LTCITies, "CITY_ID", "CITY_NAME", 1);
var entry = new Models.TRRESPONDENT
{
ENTRY_DATE = DateTime.Now,
AUDIT_TIME = DateTime.Now,
};
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "RESPONDENT_ID,BC_ID,BINUSIAN_ID,FULL_NAME,EMAIL,PHONE_NUMBER,ADDRESS,CITY_ID,ZIP_CODE,SOURCE_ID,ENTRY_DATE,PACKAGE,AUDIT_USER_NAME,AUDIT_TIME,AUDIT_ACTIVITY")] TRRESPONDENT tRRESPONDENT)
{
if (ModelState.IsValid)
{
db.TRRESPONDENTs.Add(tRRESPONDENT);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.CITY_ID = new SelectList(db.LTCITies, "CITY_ID", "CITY_NAME", tRRESPONDENT.CITY_ID);
return View(tRRESPONDENT);
}
}
Upvotes: 1
Views: 1145
Reputation:
You have not stated the details of the error message, but no doubt this is because you saving a values of 01/01/0001
to a field which which is DATETIME
(which only accepts dates between 01/01/1753
to 12/31/9999
) and not DATETIME2
.
The reason the values of you dates are 01/01/0001
(which is the default for DateTime
) is because you do not pass a model to the view so default values are used. The code in your GET needs to be
public ActionResult Create()
{
ViewBag.CITY_ID = new SelectList(db.LTCITies, "CITY_ID", "CITY_NAME", 1);
var entry = new Models.TRRESPONDENT
{
ENTRY_DATE = DateTime.Now,
AUDIT_TIME = DateTime.Now,
};
return View(entry); // return your model
}
However you should not use your data model in the view, and instead create a view model containing only the properties you need. Values such as ENTRY_DATE
should only be set immediately before you save the data model to the database. For information on a creating a view model, refer What is ViewModel in MVC?.
The basic steps for creating a view model are
ViewModels
and copy you data model to and
and rename it (say)RespondentVM
[Display]
attributes from you data model (they are
view specific attributes)ENTRY_DATE
and AUDIT_TIME
) except the property which
is the objects ID which should be renamed to ID
so its
automatically bound assuming your using the default routes (note its
not clear if you even have an ID property - I assume its
RESPONDENT_ID
, but that should be an auto-incremented int
in the
database -i.e. [Key]public int RespondentId { get; set; }
). I also
recommend you rename all your properties to follow naming
conventions - EntryDate
, not ENTRY_DATE
.nullable
and add the [Required]
attribute to protect against under-posting attacks (e.g. public int
CITY_ID { get; set; }
becomes public int? CityID { get; set; }
SelectList
's etc that you are
currently assigning to ViewBag
properties, e.g. public
IEnumerable<SelectListItem> CityList { get; set; }
You controller methods will then be
public ActionResult Create()
{
RespondentVM model = new RespondentVM();
ConfigureViewModel(model);
return View(model);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(RespondentVM model) // note a [Bind]` attribute is not required
{
if (!ModelState.IsValid)
{
ConfigureViewModel(model);
return View(model);
}
// Initialize an instance of your data model and set its properties based on the view model
TRRESPONDENT respondent = new TRRESPONDENT()
{
FULL_NAME = model.FullName,
CITY_ID = model.CityID,
....
// Set default values
ENTRY_DATE = DateTime.Now,
....
}
db.TRRESPONDENTs.Add(respondent);
db.SaveChanges();
return RedirectToAction("Index");
}
// Common code for populating SelectLists etc - DRY!
private void ConfigureviewModel(RespondentVM model)
{
// Note - delete the 4th parameter of the SelectList constructor
model.CityID = new SelectList(db.LTCITies, "CITY_ID", "CITY_NAME");
}
And a few extra notes on your view code.
ID
and your using the default routing[Display(Name = "..")]
attributes, then in the view
its just @Html.LabelFor(m => m.PropertyName)
, not
@Html.LabelFor(m => m.PropertyName, "some text")
@Html.DropDownListFor(m =>
m.CityID, Model.CityList, "Please select", new { ... });
- you
current implementation will not give correct 2-way model binding or
client side validation.Upvotes: 1