0

First, sorry for my bad English. I am from Brazil. And I am a beginner in .NET MVC5.

I had a model class Task with ID plus 4 editable columns. When creating a new Task, the user must fill out only 2 of them (TaskType and Subject). The remaining two columns (UserID and CreationDate) must be populated with information obtained from the system: user ID and current date.

Then, in the Create Get, I put this two information in the ViewBag:

public ActionResult Create()
{
    ViewBag.TaskTypeID = new DAO.TaskTypesDAO().ListOfTypes();
    ViewBag.ApplicationUserId = User.Identity.GetUserId();
    ViewBag.CreationDate = DateTime.Now;
    return View();
}

And in View Create I tried to include this information first, without showing it:

First, I tried HiddenFor() and after with DisplayFor()

@Html.LabelFor(model => model.CreationDate, "Creation Date")
@Html.DisplayFor(model => model.CreationDate)
@Html.HiddenFor(model => model.CreationDate)

@Html.LabelFor(model => model.ApplicationUserId, "Creator")
@Html.DisplayFor(model => model.User.Id)
@Html.HiddenFor(model => model.ApplicationUserId)

DisplayFor() doesn't show anything.

And when I submit the Post Create method

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "ID,TaskTypeID,Subject,CreationDate,ApplicationUserId")] Task task)
{   
    if (ModelState.IsValid)
    {
        db.Tasks.Add(task);
        db.SaveChanges();
        return RedirectToAction("Index");
    }
    ViewBag.TaskTypeID = new DAO.TaskTypesDAO().ListOfTypes();
    ViewBag.ApplicationUserId = User.Identity.GetUserId();
    ViewBag.CreationDate = DateTime.Now;
    return View(tarefa);
}

The ModelState is invalid and task.CreationDate and task.ApplicationUserId are empty.

How can include this two information before the create post bind????

or else, How can include after and revalidate ModelState??

or .....

Neumann
  • 319
  • 2
  • 14
  • Your not even passing a model to your view (you `HtmlHelper` methods bind to the properties of your model, not to `ViewBag`). But in any case, this as all wrong. You do not set the values of `ApplicationUserId` and `CreationDate` in the the GET method, or include form controls for them in the view - you set them in the POST method immediately before you save the object. And strongly recommend you read [What is ViewModel in MVC?](http://stackoverflow.com/questions/11064316/what-is-viewmodel-in-mvc) –  Feb 22 '17 at 01:16

1 Answers1

0

I don't understand why are you sending CreationDate and ApplicationUserId to the view through ViewBag and posting it back, this doesn't make any sense. Someone could easily edit the html and forge the ApplicationUserId or CreationDate.

I think your life would be much easier if you just use a strong typed view for this. My 2 cents for you would be:

Put everything you want to display inside a view model (dropdowns, lists, etc.). Here you could propably use fill a SelectListItem to show your tasks types on a dropdown (or a enum if it's simple enough).

[HttpGet]
public ActionResult Create()
{
     var viewModel = new CreateTaskViewModel
     {
          // [...] Put info that you need to display on the view here        
      }

     return View(viewModel);
}

Get current date and user id when creating the task, that way the user can't forge this information. After creating the task, if you want to show it to the user, just use a Show view.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(CreateTaskViewModel createTaskViewModel)
{   
   // If validation fails return to the view showing the errors
    if (!ModelState.IsValid) { return View(createTaskViewModel); }

    // [...] Create task object using info from viewModel
    // and what else is necessary

    db.Tasks.Add(task);
    db.SaveChanges();

    // [...] Fills view model to show info and redirect

    return RedirectToAction("Show", showViewModel);
}

Use a model on the view and don't put sensitive information hidden on your html.

@model CreateTaskViewModel

@Html.LabelFor(model => model.TaskType)
// Or a dropdown list
@Html.TextBoxFor(model => model.TaskType)

@Html.LabelFor(model => model.Subject)
@Html.TextBoxFor(model => model.Subject)

Another thing that can be really usefull for you to study is the PRG (Post Redirect Get) pattern. It comes in handy when you have more complex action/ views.

Thiago M
  • 181
  • 4
  • 23
  • This is exactly what I wanted, another way to make it work. As I said, I'm just starting .NET MVC5 and I'll rather follow your suggestion and study the Post Redirect Get (PRG) pattern.Thanky you, so much. – Neumann Feb 22 '17 at 20:04
  • @Neumann You're welcome. Don't forget to set the answer for this question ;) – Thiago M Feb 22 '17 at 20:07