1

I have this code in C# using EF Core 1.2 where I have a form containing two submit buttons. The first button 'upload' invokes my method 'UpLoadMyFile' which compares each line from my textarea to a pattern and returns a string which tells me if it matches one pattern. Then I add all my text and its states into a

 List <Tuple<string, string>> 

that I pass to my View via a ViewModel and display each line plus its state in a table.

Now I'm trying to save each line into my database when I click my second button 'save'. But every time I try to save my lines a NullReferenceException occurs which tells me my List from my table is null.

I would like to know how to pass all lines and states from my Table 'MyTupleList' to my Post Method since I really don't know how to fix my problem.

My View:

@model Models.ViewModels.CreateSaetzeModelView
<form asp-action="ProcessCreateLines" asp-controller="SoftwareService" method="post" enctype="multipart/form-data">

<div class="div-marginBottom">        
    <table class="table">           
        <tbody>
            <tr>
                <td>
                    <textarea name="ExpressionTextarea" id="ExpressionTextarea" runat="server" TextMode="MultiLine" asp-for="@Model.LoadExpressions"></textarea>

                    <div class="col-md-10">
                        <input type="submit" name="upload" value="upload" /> !--Calls 'uploadmyfile' action-->
                    </div>
                </td>
                <td></td>
            </tr>
        </tbody>
    </table>
</div>
<br />
<div class="div-ExpressionEingabe">

</div>
@if (Model.MyLinesList != null)
{
    <div class="div-marginBottom">
        <table id="MyTupleList" class="table table_align">
            <thead>
                <tr>
                    <th>
                        State
                    </th>
                    <th>
                        MyLines
                    </th>
                </tr>
            </thead>
            <tbody>   

                    @foreach (var item in Model.MyLinesList)
                {
                    <tr>
                        <td>                               
                            @Html.DisplayFor(modelItem => item.Item2)
                        </td>
                        <td>
                            @Html.DisplayFor(modelItem => item.Item1)                            
                    </tr>
                }

            </tbody>
        </table>
        <input type="submit" name="save" value="save" />
    </div>
}

My Code:

    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> ProcessCreateLines(string upload, string save, CreateLinesModelView cmv)
    {           
        //Button 'upload': Checking my lines 
        if (!string.IsNullOrEmpty(upload))
        {
            string expressions = Request.Form["ExpressionTextarea"].ToString();

            List<Tuple<string, string>> result = new FileUploadController().CheckExpressions(expressions);

            cmv.MyLinesList = result;

            return View("ProcessCreateLines", cmv);

        }

        //Button 'save': Saving my lines into a Database
        if (!string.IsNullOrEmpty(save))
        {
    // ****************************MyLinesList is null*******************
            var list = cmv.MyLinesList;

            ...saving my list into database...
            }

        }
Joe Jonsman
  • 103
  • 1
  • 6
  • Your view is not storing the content of `MyLinesList` (it is only displaying it with labels, not as form data). When you then click the save button, the form has no `MyLinesList` data to send to the controller, which means that the `MyLinesList` property will be `null` when the model gets populated. Your `ProcessCreateLines` method is also violating SRP, as you're forcing two completely separate pieces of logic to work in the same method (with no discernible justification for doing so) – Flater Sep 08 '17 at 10:35
  • @Flater How do I store the content in my view? I tried e.g. replacing @Html.DisplayFor(modelItem => item.Item2 with – Joe Jonsman Sep 08 '17 at 10:51
  • I'm not sure how to store a `List`, I would assume that a simple `HiddenFor` is incapable of automatically doing so (but by all means, try it. If it works, you have your answer). If I figure out a way, I'll post an answer. – Flater Sep 08 '17 at 10:59
  • 1
    Not only are you not creating any form controls (so there is nothing to be sent in the request, you cannot use a `Tuple` because it has no parameterless constructor (in cannot be initialized in the POST method) and you cannot use a `foreach` - refer [this answer](http://stackoverflow.com/questions/30094047/html-table-to-ado-net-datatable/30094943#30094943) –  Sep 08 '17 at 11:06

1 Answers1

1

I managed to solve my problem thanks to the comment of @StephenMuecke by using instead of a Tupel a selfmade class

public class MyListModel
{
    public string myLine { get; set; }
    public string myState { get; set; }
}
}

and creating a List out of it in my ViewModel

public List<MyListModel> LineWithState { get; set; }

Also in my View I replaced the foreach loop with a for loop

@for (int i = 0; i < Model.LineWithState.Count; i++)
                {
                    <tr>
                        <td>
                            @Html.TextBoxFor(m=>m.LineWithState[i].myState)
                        </td>
                        <td>
                            @Html.TextBoxFor(m=>m.LineWithState[i].myLine)
                    </tr>

                }
Joe Jonsman
  • 103
  • 1
  • 6