views:

35

answers:

2

Hi, I've been reading stackoverflow for a few years now, but this is the first time I really need to post a question as I can't seem to find a suitable answer anywhere.

The thing is, I want to pass an object (a LinqToSQL entity to be precise) to my View, allow the user to add some properties, and then post it back to save it.

My object, called Probation, has a few properties (id, forpost, forcomment, user, starting, hours) and some related entity references. The forpost and forcomment entities are nullable as a user can be probated for making an offensive post or an offensive comment. Please mind that forpost refers to an Idea entity, I don't know what I was thinking calling it a post.

So here's my controller logic:

        [Authorize(Roles = "Admin, Moderator")]
    public ActionResult ProbateUser(int? post, int? comment)
    {
        if (post != null)
        {
            Idea idea = irep.GetIdea(post ?? 0);
            Probation probation = new Probation
            {
                user = (Guid)idea.user,
                Idea = idea
            };
            return View(probation);
        }
        if (comment != null)
        {
            Comment rcomment = crep.GetComment(comment ?? 0);
            Probation probation = new Probation
            {
                user = rcomment.user,
                Comment = rcomment
            };
            return View(probation);
        }

        return View("NotFound");
    }

    [AcceptVerbs(HttpVerbs.Post)]
    [Authorize]
    public ActionResult ProbateUser(Probation probation, FormCollection values)
    {           
        try
        {
            probation.starting = DateTime.Now;
            rep.ProbateUser(probation);
            rep.Save();
            return RedirectToAction("Index");
        }
        catch
        {
            return View("NotFound");
        }
    }

}

And here's the view, using hidden fields to store the preset values:

        <fieldset>
        <legend>Fields</legend>
            <%: Html.Hidden("Idea", Model.Idea)%>
            <%: Html.Hidden("Comment", Model.Comment)%>
            <%: Html.Hidden("user", Model.user) %>
        <div class="editor-label">
            <%: Html.LabelFor(model => model.reason) %>
        </div>
        <div class="editor-field">
            <%: Html.TextAreaFor(model => model.reason) %>
            <%: Html.ValidationMessageFor(model => model.reason) %>
        </div>


        <div class="editor-label">
            <%: Html.LabelFor(model => model.hours) %>
        </div>
        <div class="editor-field">
            <%: Html.TextBoxFor(model => model.hours) %>
            <%: Html.ValidationMessageFor(model => model.hours) %>
        </div>

        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>

Now my problem is, once the Probation object is posted back, the nullable fields forcomment and forpost are always null!

So to summarize: what is the correct way of passing objects with nullable properties from Controller->View->Controller? Pretty please?

A: 

It's because of the statelessness of MVC. If you want to those fields to retain its values, you will need to put them in hidden fields so then they are binded back during post, like such:

...
<legend>Fields</legend>
    <%: Html.Hidden("Idea", Model.Idea)%>
    <%: Html.Hidden("Comment", Model.Comment)%>
    <%: Html.Hidden("user", Model.user) %>
    <%: Html.Hidden("user", Model.ForPost) %>
    <%: Html.Hidden("user", Model.ForComment) %>
<div class="editor-label">
...
Johannes Setiabudi
But that's exactly what I'm doing now?? Or am I missing something here?The problem is that, using this method, all *nullable* fields, regardless of value, are *set to* null. I can have regular properties with no problem.
Kris9000
A: 

Okay, from what I've gathered from comments here and on other forums: there is simply no way to pass nullable fields and get them posted back. My workaround for this was building a partial Probation class that adds two non-nullable value fields to the Probation entity, and to use these to populate the fields after postback. As a (better) alternative, making ViewModels would work as well.

Kris9000