2

I'm not so experienced using MVC. I'm dealing with this situation. Everything works well until call the HttpPost method where has all its members null. I don't know why is not persisting all the data on it.

And everything works well, because I can see the data in my Html page, only when the user submit the information is when happens this.

    [HttpGet]
    public ActionResult DoTest()
    {
        Worksheet w = new Worksheet(..);
        return View(w);
    }

    [HttpPost]
    public ActionResult DoTest(Worksheet worksheet)
    {
        return PartialView("_Problems", worksheet);
    }

enter image description here

This is class which I'm using.

public class Worksheet
{
    public Worksheet() { }

    public Worksheet(string title, List<Problem> problems)
    {
        this.Title = title;
        this.Problems = problems;
    }

    public Worksheet(IEnumerable<Problem> problems, WorksheetMetadata metadata, ProblemRepositoryHistory history)
    {
        this.Metadata = metadata;
        this.Problems = problems.ToList();
        this.History = history;
    }

    public string Title { get; set; }
    public List<Problem> Problems { get; set; }  // Problem is an abstract class
    public WorksheetMetadata Metadata { get; set; }
    public ProblemRepositoryHistory History { get; set; }
}

And my razor view.... the razor view shows successfully my view. I realized something rare, please note in my 5 and 6 lines that I have HiddenFor method, well if I used that, when calls HTTPPOST persists the data, I don't know why.

@model Contoso.ExercisesLibrary.Core.Worksheet

<div id="problemList">
<h2>@Html.DisplayFor(model => model.Metadata.ExerciseName)</h2>
    @Html.HiddenFor(model => model.Metadata.ExerciseName)
    @Html.HiddenFor(model => model.Metadata.ObjectiveFullName)

@for (int i = 0; i < Model.Problems.Count; i++)
{
    <div>
    @Html.Partial(Contoso.ExercisesLibrary.ExerciseMap.GetProblemView(Model.Problems[i]), Model.Problems[i])
    </div>
}
</div>

UPDATE I'm using a static class to get the view name, but as I'm testing I'm just using this Partial view

@model Contoso.ExercisesLibrary.AbsoluteArithmetic.Problem1
<div>

    <span style="padding:3px; font-size:18px;">@Model.Number1</span>
    <span style="padding:5px; font-size:18px;">+</span>
    <span style="padding:5px; font-size:18px;">@Model.Number2</span>
    <span style="padding:5px; font-size:18px;">=</span>

    <span style="font-size:18px">
            @Html.EditorFor(model => model.Result, new { style = "width:60px; font-size:18px;" })
            @Html.ValidationMessageFor(model => model.Result)
    </span>
</div>

@section Scripts {

}

And here the user do the post

@model Contoso.ExercisesLibrary.Core.Worksheet

<form method="post">
    @Html.Partial("_Problems", Model)

    <input type="submit" value="Continue" />
</form>
tereško
  • 58,060
  • 25
  • 98
  • 150
Darf Zon
  • 6,268
  • 20
  • 90
  • 149
  • 4
    Ahem..... I thought one of the biggies of ASP.NET MVC is: *no more postbacks* ... – marc_s Jan 10 '13 at 06:20
  • You should share your partial view – rexcfnghk Jan 10 '13 at 06:22
  • I have edited your title. Please see, "[Should questions include “tags” in their titles?](http://meta.stackexchange.com/questions/19190/)", where the consensus is "no, they should not". – John Saunders Jan 10 '13 at 06:23
  • Also you did not show where does your code (in the view) call your HttpPost action method – rexcfnghk Jan 10 '13 at 06:25
  • 1
    youve got a few problems. your main one though is that MVC cannot bind to an abstract class. So "Problems" will always have a problem (pun intended) – RPM1984 Jan 10 '13 at 06:26
  • One way is to hide all fields in View using Html.HiddenFor(); The other is get those infor from database again. – Teddy Jan 10 '13 at 06:27
  • I see, what you suggest me.. the Problem list is the main object which I need to recover after post – Darf Zon Jan 10 '13 at 06:28
  • Depends on your scenario. What are the derived classes - what do they do? Are theyre multiple ones rendered on the page? also don't use @Html.Partial for forms - the model binder won't work because the form values don't match up to the model hierachy. – RPM1984 Jan 10 '13 at 06:29
  • Just Problem1 is derived from Problem – Darf Zon Jan 10 '13 at 06:30
  • @DarfZon - why have an abstract class with only one implementation? Doesn't make any sense. – RPM1984 Jan 10 '13 at 23:34
  • @RPM1984 It's just a demo, Problem really has more than 100 implementations – Darf Zon Jan 10 '13 at 23:58

5 Answers5

3

The Model Binder will 'bind' or link input fields on your view to the model. It will not bind display fields (like label), that is why you need the HiddenFor it will add an <input type="hidden" which will then be bound to the Model when you Post.

robasta
  • 4,621
  • 5
  • 35
  • 53
  • Now I understand, thank you.. but I guess I'm missing something.. please note in the post that I have a Partial View where uses a model called Problem1 and used a EditorFor, so this is an input control and don't get the result after post. – Darf Zon Jan 10 '13 at 06:29
  • Problem1 is an implementation of Problem (abstract class) – Darf Zon Jan 10 '13 at 06:29
1

You can use 'TempData'. It is used to pass data from current request to subsequent request means incase of redirection.

This link also helps you.

TempData

SO Tempdata

Community
  • 1
  • 1
RGR
  • 1,521
  • 2
  • 22
  • 36
0

Make sure your form tag looks like the following, for instance the controller name, action method, the form method and an id for the form. I am referring to the @using statement. In my case the controller name is RunLogEntry, the action method is Create and the id is form.

Normal Post from View to Controller

@using (Html.BeginForm("Create", "RunLogEntry", FormMethod.Post, new { id = "form", enctype = "multipart/form-data" }))
    {
        <div id="main">
            @Html.Partial("_RunLogEntryPartialView", Model)
        </div>
    }

If you want to post via Jquery, could do the following:

$.post("/RunLogEntry/LogFileConfirmation",
              $("#form").serialize(),
               function (data) {
                   //this is the success event
                   //do anything here you like
                                                            }, "html");
tam tam
  • 1,870
  • 2
  • 21
  • 46
0

You must specify a form with correct attribute in your view to perform post action

<form action="Test/DoTest" method="post">
...
</form>

or

@using(Html.BeginForm("DoTest", "Test", FormMethod.Post)) {
...
}

The second is recommended.

phnkha
  • 7,782
  • 2
  • 24
  • 31
0

Put your entire HTML code under:

@using(Html.BeginForm())

tag.

Jitender Kumar
  • 2,439
  • 4
  • 29
  • 43