0

I have a little serach box that returns results from a database. That works fine. The results are in a List page and display correctly. However, I need to take the selected object and pass it to my controller. I am getting NULL values when I debug it, and an empty results page. Here is the model:

public class CodeSnip
{
    public short Id { get; set; }
    public string Title { get; set; }
    public string Description { get; set; }
    public string Code { get; set; }
    public LangType Language { get; set; }
    public string Creator { get; set; }

}

public class ListOfCodeSnips : List<CodeSnip>
{
    public CodeSnip CodeSnip { get; set; }
}

public enum LangType
{
    CSharp,                
    css,
    HTML,
    JavaScript,
    Perl,
    PHP,
    Python,
    Ruby,
    SQL,
    VB,
    XML,
    Other
}

Here is the controller method (which does nothing atm):

    [HttpPost]
    public ActionResult Display(CodeSnip snip)
    {
        return View(snip);
    }

Here is what I have for a view. Again, it posts only NULLS for the object values:

@model Models.ListOfCodeSnips

<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(model => model.CodeSnip.Title)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.CodeSnip.Description)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.CodeSnip.Language)
        </th>
        <th>
            @Html.DisplayNameFor(model => model.CodeSnip.Creator)
        </th>
    </tr>

    @using (Html.BeginForm("Display", "Home", FormMethod.Post))
    {


    foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.Title)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Description)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Language)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Description)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Creator)
        </td>
        <td>
            <input type="submit" value ="Display"/>
        </td>
    </tr>
        }
    }
</table>

so, in short, what I want to do is take the selected model-item from the view and pass it into my controllers Display method, but as I said, all I get are nulls. I have looked around and all i find are examples f how to pass a List of objects. I tried monkeying with those, but got nothing.

Thanks for your time.

rigamonk
  • 1,179
  • 2
  • 17
  • 45
  • if you aren't doing any calculations or trying to save/change values to the db, and instead just want to *display* them.. why are using a `HttpPost` request and not a `HttpGet` request? – Grizzly Aug 30 '16 at 14:24
  • Is there an advantage to such an approach, and if so, how would I do it? I tried it with an ActionLink and still couldn't pass the object – rigamonk Aug 30 '16 at 14:27

2 Answers2

1

Since you said that you have tried with ActionLink and it did not work, here is how it would work.. instead of passing the type that you are looking for as a parameter for the Display action, pass the ID of the record.

So it would look something like this:

Controller Action

[HttpGet]
public ActionResult Display(int id)
{
    var snip = db/* connection string */.TableName.Find(id);
    return View(snip);
}

ActionLink

@Html.ActionLink("Display", "Display", "ControllerName", new { id = item.Id }, null )

// Or if you want a button that acts as a link, and not just a plain link

<input type="button" class="btn" value="Display" onclick="location.href='@Url.Action("Display", "ControllerName", new { id = item.Id })'" />

Let me know if this helps!

Grizzly
  • 5,873
  • 8
  • 56
  • 109
  • I've though of doing that, but I would prefer not to make a second call to the database (even though its fairly cheap) – rigamonk Aug 30 '16 at 14:37
  • @rigamonk okay, but that explains why u r getting null values when you click the button.. your code doesn't know which record you want to *display*.. you are simply calling an empty CodeSnip Model... you need to use the `ID` since it is unique for each record – Grizzly Aug 30 '16 at 14:44
0

There are two problems with your code:

1) You do not render any <input> elements in which you send the selected values back to the controller. Use Html.HiddenFor or Html.EditorFor in addition to Html.DisplayFor.

2) In order for the MVC Modelbinder to be able to bind your list, use a for loop instead of foreach.

See also MVC Form submit not transferring the updated model back to action method for List

for (var i = 0; i < Model.Count(); i++) {
    <tr>
        <td>
            @Html.DisplayFor(m => m[i].Title)
            @Html.HiddenFor(m => m[i].Title)
        </td>
        @* etc ... *@
   <tr>
}

PS: this loop would post all displayed CodeSnips, i.e. the receiving action would have the signature public ActionResult Display(ListOfCodeSnips postData).

Community
  • 1
  • 1
Georg Patscheider
  • 9,357
  • 1
  • 26
  • 36