0

My application searches for the files that contains a string the user is looking for. So far it does that perfectly. The last thing I need to do is to export it to an excel file so I added a method inside of my controller that is called by the Result page after I press a button.

The results are stored in a List of type Result which is a class with four variables.

The method ExportToExcel currently returns string so that I can test if the list of results is null. Every single time it has come out as "No Data", therefore it is null. It perfectly prints out a table with the information in the Results page but does not have the information when i want to export it.

Why is my model not passing from view to method?

At first I wanted to pass my model so that I can access the information in the List but now I am wondering if it would be better to save the List data in the controller so that I can directly pass it to my method.

Either way would be fine and I am open to any other ways to do this.

Model

namespace Final.Models
{
    public class InputModel:Result
    {

        public List<Result> Results { get; set; }

    }  
}

Controller

This controller is just showing how I am passing the InputModel between the views and method. Maybe I am doing something wrong here?

        public ActionResult Index()
        {
            var input = new InputModel();
            return View(input);
        }

        [HttpPost]
        public ActionResult Index(InputModel input)
        {
            //Finds files that contain string.
            //send model to Result
            return View("Result", input);
        }

        public ActionResult Result(InputModel input)
        {
            return View(input);
        }

        [HttpPost]
        public string Result(InputModel input,string export)
        {

            return ExportToExcel(input);
        }

        public string ExportToExcel(InputModel input)
        {
            if (input.Results!=null)
            {
                //Run excel code here
              return "Excel Exported";
            }
            else
             {
                 return "No Data";
             }
        }

View for Result

This is part of the view, not the whole thing. I didn't think the full view was necessary but I posted it in the bottom just in case.

 @foreach(var result in Model.Results)
        {

            <tr>
             //Return graph of information received
            </tr>

        }
    </table>

     <form action="Find/Result" method="POST">
           <input type="submit" value="Export" name="export"  class="btn btn-default"> 
     </form>

Output

Occurs after pressing the "Export" Button

"No Data"

This is my first MVC applications so once again please let me know if there is any other area I can improve in.

Full View For Result

Changed the form to enclose the entire view as suggested by Wubbly but I get the same output.

@model Final.Models.InputModel

@{
    ViewBag.Title = "Result";
    Layout = "~/Views/Shared/_Layout.cshtml";
}




    <br />
    <h4>Result</h4>
    <hr />


@using (Html.BeginForm("Result", "Find", FormMethod.Post))
{
    <p>The <b>@Model.SelectedText</b> files that contain <b>"@Model.Find"</b> are:  </p>
    <div>
        <table class="table table-bordered table-responsive table-hover">
            <tr>
                //HEADERS

            </tr>
            @foreach (var result in Model.Results)
            {
                // int i = 1;
                <tr>

                    <td>@result.SelectedText</td>
                    <td>@result.FileName</td>
                    <td>@result.Line</td>
                    <td>@result.LineCode</td>
                </tr>

            }
        </table>

        <div class="form-group">
            <div class="col-md-offset-2 ">

                <input type="submit" value="Export" name="export" class="btn btn-default">


            </div>
        </div>

    </div>
}







    <p>
        @Html.ActionLink("Back to List", "Index")
    </p>
Jessica G.
  • 101
  • 7
  • 2
    It looks like you're submitting an empty form, as you can see your form only contains a button and nothing else, which is why the `input.Results` is null. – Wubbler Jun 29 '18 at 19:33
  • Why would you expect the InputModel to be populated if the form you submit is empty? – mason Jun 29 '18 at 19:49
  • Is that your complete view? Have you copied everything to your question? – bsod_ Jun 29 '18 at 19:56
  • @bsod_ no it is not the complete view. i shortened i to make it easier to read but the rest is just divs and formatting stuff. – Jessica G. Jun 29 '18 at 20:01
  • @Wubbler I see... Maybe Im just confused on how http forms work but then how will httpget run if I cover the entire view in httppost??? – Jessica G. Jun 29 '18 at 20:03
  • @Wubbler I still get the same error. even when I cover the entire view in the form – Jessica G. Jun 29 '18 at 20:05
  • 1
    You're still not submitting any form elements. You should probably learn the basics of HTML Forms and how they POST data to web servers before learning ASP.NET MVC. – mason Jun 29 '18 at 20:44
  • Ok will do. Thank you for your advice @mason. – Jessica G. Jun 29 '18 at 20:50
  • 1
    Your form has not form controls, so there is nothing to submit. And if you include form controls, then you cannot use a `foreach` loop (refer [this answer](http://stackoverflow.com/questions/30094047/html-table-to-ado-net-datatable/30094943#30094943). But what is the point of this - you are not editing anything so why in the world would you send back to the controller all the data you just sent from the controller - its just pointless extra overhead that would be degrading performance. If you need the data, then you get it again in the controller by calling the database. –  Jun 29 '18 at 22:47
  • @StephenMuecke There is no database being used here that's why I am trying to pass the same model with the same information between views. The information is user input that is not being saved. So if its not database how can I access the information again in another view? Because each time I want to use the model in a view I have to create a new model but then wouldn't I lose the information I received from the user? **Had to repost it because i wrote controller instead of views** – Jessica G. Jul 02 '18 at 13:39
  • Well the data obviously can from somewhere initially - so what ever method you used to get the data in the first place, you just repeat again –  Jul 02 '18 at 13:42

2 Answers2

0

Use for loop with hidden property which takes your property value to model.

@using (Html.BeginForm("Result", "Find", FormMethod.Post))
 {
<p>The <b>@Model.SelectedText</b> files that contain <b>"@Model.Find"</b> are:  </p>
<div>
    <table class="table table-bordered table-responsive table-hover">
        <tr>
            //HEADERS

        </tr>
        @for (int i = 0; i < Model.Results.Count; i++)
        {
            // int i = 1;
            <tr>
                <td>
                    @Html.HiddenFor(r => r.Model.Results[i].SelectedText)
                    @Html.HiddenFor(r => r.Model.Results[i].FileName)
                    @Html.HiddenFor(r => r.Model.Results[i].Line)
                    @Html.HiddenFor(r => r.Model.Results[i].LineCode)

                    @Html.DisplayFor(r => r.Model.Results[i].SelectedText)
                </td>
                <td>@Html.DisplayFor(r => r.Model.Results[i].FileName)</td>
                <td>@Html.DisplayFor(r => r.Model.Results[i].Line)</td>
                <td>@Html.DisplayFor(r => r.Model.Results[i].LineCode)</td>
            </tr>

        }
    </table>

    <div class="form-group">
        <div class="col-md-offset-2 ">

            <input type="submit" value="Export" name="export" class="btn btn-default">


        </div>
    </div>

</div>
 }
 <p>
   @Html.ActionLink("Back to List", "Index")
 </p>
Shailendra Kumar
  • 138
  • 2
  • 12
0

To anyone who might need an answer and is in a similar situation I figured my problem out. Many of you might not think it is the right way to fix it but it is what worked for me. Either way any feedback would be appreciated to improve my abilities.

First, I did change my foreach to a for loop as recommended by StephenMuecke and ShailendraKumar.

The way I transferred the data from my HTTPGet to my HTTPPostis with TempData. I used it to store my model with the user's input inside my HTTPPost Index and called it in my HTTPPost Result.

Here's how I changed my controller.

       public ActionResult Index()
        {
            var input = new InputModel();
            input.Type = input.FillType(input.Type);

            return View(input);
        }

        [HttpPost]
        public ActionResult Index(InputModel input)
        {
            input.FileType = input.ValueConvert();
            input.FileFind();
            TempData["model"] = input
            return View("Result", input);
        }

        public ActionResult Result(InputModel input)
        {
            return View(input);
        }


        [HttpPost]
        public void Result()
        {
            InputModel model = new InputModel();
            model = (InputModel)TempData["model"];
            model.ExportToExcel();
        }
Jessica G.
  • 101
  • 7