0

I am new to MVC3 and trying to work on my first small project at work. I have a HomeController with two actions, Index() and GetData(). Index just returns the Index view. When the Index page loads, I want there to be an html Button or Input of type Button. When I click on this button, I want the GetData action to run, which selects some data based on a linq query and returns a List. Then in the Index view itself, below the button which i clicked, I want the list to be populated onto an html table .....I assume using a foreach loop.

This is not working, and I think I am clearly misunderstanding the concept of this MVC pattern.

My Controller Code:

    private ReferenceDataContext data = new ReferenceDataContext();

    public ActionResult Index()
    {

        return View();

    }

    public ActionResult GetData()
    {

        using (data)
        {                
            var hosp = (from x in data.Hospitals
                          where x.HAcode == "Q36"
                          select x).ToList();
            ViewData["hosp"] = hosp;
            return RedirectToAction("Index");                
        }

    } 

My View Code:

@model IEnumerable<NursingHomes.Models.Hospitals>

@{
    ViewBag.Title = "Hospitals Verify";
}


<br />
<br />
@using (Html.BeginForm("GetData", "Home")) 
{ 
<input type="submit" value="Submit" title="Get Data" />  

<h2>Nursing Homes</h2>

<table>
<tr>
<th>Code</th>
<th>HAcode</th>
<th>Name</th>

</tr>

@foreach (NursingHomes.Models.Hospitals item in (List<NursingHomes.Models.Hospitals>)    ViewData["hosp"])
{ 
<tr>
<td>
@Html.DisplayFor(modelItem=>item.Code)
</td>
<td>
@Html.DisplayFor(modelItem=>item.HAcode)
</td>
<td>
@Html.DisplayFor(modelItem=>item.Name)
</td>

</tr>

}

</table>

} 

I am doing something wrong above? Is is this simply not possible without the use of JQuery?

Basic question is, how can click on that button on the Index page, and tell it to run the GetData action and then build the table below the button using the returned List from the GetData action.

matthias krull
  • 4,389
  • 3
  • 34
  • 54
Antz
  • 3
  • 1
  • 2

2 Answers2

1

Try returning View from Get Data Action as below:

return View("Index",YourModelObject);

and you can use this Model in view as Below:

...
<table>
<tr>
<th>Code</th>
<th>HAcode</th>
<th>Name</th>

</tr>
If(Model !=null)
{
@foreach (NursingHomes.Models.Hospitals item in Model)
{ 
<tr>
<td>
 .....

EDIT: If you want keep URL as Same then use index action for POST action also as below:

public ActionResult Index()
        {
            if (Request.HttpMethod.ToLower().Equals("get"))
            {
                return View();
            }
            else
            {
                using (data)
                {
                    var hosp = (from x in data.Hospitals
                                where x.HAcode == "Q36"
                                select x).ToList();

                    return View(hosp);
                }
            }
        }

In your View you should remove the action name and controller name params.

@using (Html.BeginForm("GetData", "Home")) 
{ 
<input type="submit" value="Submit" title="Get Data" /> 
.....

Hope this helps.

Mohan
  • 1,051
  • 1
  • 9
  • 22
  • Hi, thanks for your reply. I tried what you suggested, I get "Object Ref not set to instance of an object" pointing at the "foreach" loop. I don't want the table to be populated when the page loads, but only when i click the GetData button. Thanks – Antz Oct 22 '12 at 17:15
  • Hello again, I included the If statement which you showed above and it worked. It was my mistake that I didn't include it initially. So, thanks very much for your help. Much appreciated. just one question, even though the button works and shows the list properly, address bar shows /home/getdata....how can I make it show just /home. Is this possible? – Antz Oct 22 '12 at 17:39
  • Thank you very much. It was exactly what I was looking for. Although there might be other better ways to achieve what I am trying to do, for example using JQery ajax to fill the data in the html table when Submit button is clicked, this works fine for me now...........but, how COULD you do the same above but fill the table using jquery ajax? I just cant help but wonder if that might be a better solution? – Antz Oct 23 '12 at 13:58
  • You can also do this by using JQuery.. By doing in that we have some advantages like doesn't need to postback page. – Mohan Oct 23 '12 at 17:14
0

You need to separate the code as follows:

  1. The index view which will contain the button
  2. The data view containing the table.

Index View:

    @{
        ViewBag.Title = "Hospitals Verify";
    }

    @using (Html.BeginForm("GetData", "Home")) 
    { 
        <input type="submit" value="Submit" title="Get Data" />  
    }

GetData View:

    @model IEnumerable<NursingHomes.Models.Hospitals>
    @{
        ViewBag.Title = "Hospitals Verify";
    }

    @using (Html.BeginForm("GetData", "Home")) 
    { 
        <input type="submit" value="Submit" title="Get Data" />  
    }

    <h2>Nursing Homes</h2>

    <table>
      <tr>
       <th>Code</th>
       <th>HAcode</th>
       <th>Name</th>
      </tr>

     @foreach (var item in Model)
     { 
       <tr>
         <td>
           @Html.DisplayFor(modelItem=>item.Code)
         </td>
         <td>
           @Html.DisplayFor(modelItem=>item.HAcode)
         </td>
         <td>
           @Html.DisplayFor(modelItem=>item.Name)
         </td>
       </tr>
     }

     </table>

Then in your controller, return the Model instead of populating a separate ViewData instance

private ReferenceDataContext data = new ReferenceDataContext();

public ActionResult Index()
{

    return View();

}

public ActionResult GetData()
{
    using (data)
    {                
        var hosp = (from x in data.Hospitals
                      where x.HAcode == "Q36"
                      select x).ToList();

        return View(hosp);                
    }

} 

If you wanted to take it to the next level, you could put the GetData in a partial view and retrieve via ajax so the page is seamless and doesn't reload.

Chad Kapatch
  • 585
  • 1
  • 4
  • 16
  • Thanks for your reply. Are you essentially saying that I need to create a separate view for the GetData action? I am trying to avoid that. Also you mentioned to return the Model. If i return the model, that means I would not be getting the model which is restrcited to Q36 codes only....is that right? I need that Q36 restricted dataset only, to be returned from the model. Am I missing something? Thanks – Antz Oct 22 '12 at 18:03
  • You don't have to put them in separate views but it seems cleaner to do so. Not sure what your referring to with the Q36 codes... – Chad Kapatch Oct 22 '12 at 18:45
  • although the data model returns all the rows from the Hospitals table, as you can see in the code for GetData...i declared "var hosp" to return only those records from Hospitals table where "code=Q36". You mentioned to return the model, but I would ideally want to retun the "hosp" list. Hope i am making sense. Thanks – Antz Oct 22 '12 at 18:54
  • oh yes, sorry I was returning data instead of hosp. Return hosp. – Chad Kapatch Oct 22 '12 at 18:58
  • Hi Chad, Thanks for your help in the above. I appreciate it. I did finally get it work as I wanted. You mentioned I could do it with Ajax. Would you be able to give some advice or point me in the right direction as to how I could call GetData via jquery ajax and and populate the table in the Index view via ajax?..Thanks. – Antz Oct 23 '12 at 10:48
  • Hi, you would convert your form to having your table as a partial view, then you would follow this answer to load the html via ajax http://stackoverflow.com/questions/1570127/render-partial-view-using-jquery-in-asp-net-mvc – Chad Kapatch Oct 23 '12 at 14:36