admin管理员组

文章数量:1327806

I know this is pretty standard procedure, but yet due to some custom demands for the way the table is created I'm in trouble finding a way to read the data from the table and pass it back to the controller.

I build my table using records from the database each record holds rowNo and columnNo, and the problem is that each raw may have different number of columns. I couldn't find a proper plugin that can build this so instead I made a simple method that creates a string that I pass to the view.

Just to get the idea for what I'm talking about here is a snippet from the code where you can see how I create <td>..</td> :

sb.Append("<td>" + innerArray[a][0].QuestionText +
                                "<input type='textbox' value=" +
                                innerArray[a][0].FieldValue + "></td>");

I know it's not very smart to use StringBuilder and + but for now it works. So however, after building my string and passing it to the view I get this :

And this is the source from the View page source:

 <tr>
     <td>alabala<input type='textbox' value=></td>
     <td colspan=2><input type='textbox' value=yes></td>
 </tr>
 <tr>
     <td colspan=3>alabala<input type='textbox' value=yes></td>
 </tr>
 <tr>
     <td colspan=3>alabala<input type='textbox' value=yes></td>
 </tr>
 <tr>
     <td>alabala<input type='textbox' value=no></td>
     <td>alabala<input type='textbox' value=no></td>
     <td>alabala<input type='textbox' value=no></td>
 </tr>
 <tr>
     <td>alabala<input type='textbox' value=no></td>
     <td colspan=2><input type='textbox' value=no></td>
 </tr>
 <tr>
     <td colspan=3>alabala<input type='textbox' value=></td>
 </tr>
 <tr>
     <td colspan=3>alabala<input type='textbox' value=no></td>
 </tr>

It's how you see it - one long string containing the whole HTML code.

all text boxes are editable so what I need is a way to read the data for each text box and save/pass it along with the RowNo and ColumnNo so I can save it back in my database.

I know this is pretty standard procedure, but yet due to some custom demands for the way the table is created I'm in trouble finding a way to read the data from the table and pass it back to the controller.

I build my table using records from the database each record holds rowNo and columnNo, and the problem is that each raw may have different number of columns. I couldn't find a proper plugin that can build this so instead I made a simple method that creates a string that I pass to the view.

Just to get the idea for what I'm talking about here is a snippet from the code where you can see how I create <td>..</td> :

sb.Append("<td>" + innerArray[a][0].QuestionText +
                                "<input type='textbox' value=" +
                                innerArray[a][0].FieldValue + "></td>");

I know it's not very smart to use StringBuilder and + but for now it works. So however, after building my string and passing it to the view I get this :

And this is the source from the View page source:

 <tr>
     <td>alabala<input type='textbox' value=></td>
     <td colspan=2><input type='textbox' value=yes></td>
 </tr>
 <tr>
     <td colspan=3>alabala<input type='textbox' value=yes></td>
 </tr>
 <tr>
     <td colspan=3>alabala<input type='textbox' value=yes></td>
 </tr>
 <tr>
     <td>alabala<input type='textbox' value=no></td>
     <td>alabala<input type='textbox' value=no></td>
     <td>alabala<input type='textbox' value=no></td>
 </tr>
 <tr>
     <td>alabala<input type='textbox' value=no></td>
     <td colspan=2><input type='textbox' value=no></td>
 </tr>
 <tr>
     <td colspan=3>alabala<input type='textbox' value=></td>
 </tr>
 <tr>
     <td colspan=3>alabala<input type='textbox' value=no></td>
 </tr>

It's how you see it - one long string containing the whole HTML code.

all text boxes are editable so what I need is a way to read the data for each text box and save/pass it along with the RowNo and ColumnNo so I can save it back in my database.

Share Improve this question edited Apr 25, 2013 at 6:49 Leron asked Apr 25, 2013 at 6:37 LeronLeron 9,89640 gold badges168 silver badges265 bronze badges 4
  • Doesn't seem like a single row to me did you mean it's contained in a single table? And how do often do want to submit your data back? After every input? Once finished? – Py. Commented Apr 25, 2013 at 6:46
  • Sorry, I see that it's misleading so I edited my question. I mean that in the View Page Source the custom generated code is shown as one long string in other words - no formatting like the one you did. And the info will be submitted only on Save button click. So basically I'll submit the data only once. – Leron Commented Apr 25, 2013 at 6:51
  • I see, and do you submit your data through ajax or is it a classic submit? – Py. Commented Apr 25, 2013 at 6:52
  • Haven't decided yet. It's my first ASP.NET MVC 3 project I see that it has a lot of build in plugins and stuff, and I have a plete freedom to do the things like I want. And what I want is just to use and learn good practices which I can reuse in the future. – Leron Commented Apr 25, 2013 at 6:55
Add a ment  | 

2 Answers 2

Reset to default 5

Why don't you use a view model? What you have done with this string builder inside a controller action is something that goes against absolutely all good practices that you might have in the MVC design pattern.

So, as always you could start by defining a view model that will meet the requirements of your view:

public class ColViewModel
{
    public string RowNumber { get; set; }
    public string ColumnNumber { get; set; }
    public string QuestionText { get; set; }
    public string FieldValue { get; set; }
}

public class RowViewModel
{
    public List<ColViewModel> Columns { get; set; }
}

Alright, now let's go ahead and populate this view model and pass it to the view:

public ActionResult Index()
{
    // in your question you have shown something called innerArray, so I assume you
    // already retrieved this from your database or something:
    SomeDomainModel[,] innerArray = ...

    var model = new List<RowViewModel>();
    for (var row = 0; row < innerArray.GetUpperBound(0); row++)
    {
        var rowModel = new RowViewModel
        {
            Columns = new List<ColViewModel>()
        };
        for (var col = 0; col < innerArray.GetUpperBound(1); col++)
        {
            rowModel.Columns.Add(new ColViewModel
            {
                RowNumber = innerArray[row, col].RowNo,
                ColumnNumber = innerArray[row, col].ColumnNo,
                QuestionText = innerArray[row, col].Question,
                FieldValue = innerArray[row, col].FieldValue,
            });
        }
        model.Add(rowModel);
    }

    return View(model);
}

[HttpPost]
public ActionResult Index(List<RowViewModel> model)
{
    ...
}

and finally in your corresponding strongly typed view:

@model List<RowViewModel>
@using (Html.BeginForm())
{
    <table>
        @for (var i = 0; i < Model.Count; i++)
        {
            <tr>
                @for (var j = 0; j < Model[i].Columns.Count; j++)
                {
                    <td>
                        @Html.HiddenFor(x => x[i].Columns[j].RowNumber)
                        @Html.HiddenFor(x => x[i].Columns[j].ColumnNumber)
                        @Html.DisplayFor(x => x[i].Columns[j].QuestionText)
                        @Html.EditorFor(x => x[i].Columns[j].FieldValue)
                    </td>
                }
            </tr>
        }
    </table>

    <button type="submit">Save</button>
}

Don't pass html to your view. It's the view's responsibility to do that. I would first question the schema of your database (why does the db care about how the data will be represented by the view?). Let's assume that we don't change anything there. The way to do this is to create a View Model. I can't code it with the info you're giving us (what's the format of the data ing from the db?). But here's pseudocode.

  1. Controller retrieves records from the database
  2. Controller creates a View Model (let's call it RowModel) for each row record and fills it with the column data. You end up with a List. Let's call that rowModels.
  3. The controller calls the view with that data `return View(rowModels)
  4. The view declares a @model List<RowModel> at the top of the code.
  5. Your Razor code interates through the rows in the model and build the HTML.
  6. Create another Controller Action MyAction(List<RowModels). This is what will be called on submit. Simply iterate through the rows and perform any db update needed.

Another advantage of using View Models is that you can specify the validation that will be used for the fields instead of relying on the (possibly missing) db model validation. See this.

本文标签: cRead data from a table and pass it to a controller in aspnet mvc3Stack Overflow