We are trying to create Excel-import feature to our website where we provide some templates that the users can fill out and then we filter out the information and post it in our database eventually.
First they download the template, fill it out and then upload it to the page. Then we go to the controller and fill out the information in our model (this works) and we print it on the page as a formatted table. Then when they confirm that the table we showed matched their Excel-document they click the "ConfirmCustomOrder"-button.
The problem: How do we get the information from the model we posted back in our controller? We would want to use the Model.CustomOrderList just as it is in the model to later validate the information and post it to our database and complete the import. But when we press the "ConfirmCustomOrder"-button we get that our ExcelModel (parameter in the controller) is null.
Model
public class ExcelModel
{
// Custom class with all Custom Order fields.
public IEnumerable<CustomOrderRow> CustomOrderList { get; set; }
// Custom class with all Purchase Order fields.
public IEnumerable<PurchaseOrderRow> PurchaseOrderList { get; set; }
public bool TriggerOnLoad { get; set; }
public string TriggerOnLoadMessage { get; set; }
}
Controller
public class ExcelController : Controller
{
// GET: Excel
public ActionResult Excel()
{
if (Session["myID"] == null)
{
return ExpireSession();
}
var model = new ExcelModel
{
CustomOrderList = null,
PurchaseOrderList = null,
TriggerOnLoad = false,
TriggerOnLoadMessage = string.Empty
};
return View(model);
}
[HttpPost]
public ActionResult Excel(FormCollection formCollection, ExcelModel model)
{
if (Session["myID"] == null)
{
return ExpireSession();
}
if (!ModelState.IsValid)
return View(model);
// If the user confirmed the information displayed.
if (Request.Form.AllKeys.Contains("ConfirmCustomOrder"))
{
return ConfirmExcelDocument(model);
}
// Otherwise assume the user is trying to upload a new file.
model = new ExcelModel
{
CustomOrderList = null,
PurchaseOrderList = null,
TriggerOnLoad = false,
TriggerOnLoadMessage = string.Empty
};
// Read excel file and create the list in the ExcelModel object.
var file = Request?.Files["UploadedFile"];
if (file == null || (file.ContentLength <= 0) || string.IsNullOrEmpty(file.FileName))
return View(model);
using (var package = new ExcelPackage(file.InputStream))
{
var currentSheet = package.Workbook.Worksheets;
var workSheet = currentSheet.First();
switch (workSheet.Cells[1, 1].Value.ToString().Trim())
{
case "Custom Order":
// Custom order
IterateCustomOrder(model, workSheet);
break;
case "Purchase Order":
// Purchase order
IteratePurchaseOrder(model, workSheet);
break;
default:
model.TriggerOnLoadMessage = "Incorrect file format, please use our template.";
model.TriggerOnLoad = true;
model.CustomOrderList = null;
model.PurchaseOrderList = null;
return View(model);
}
}
return View(model);
}
[HttpPost]
public ActionResult ConfirmExcelDocument(ExcelModel model)
{
// Later we want to further validate the information here. Currently we only print the TriggerOnLoadMessage on the screen after the "Confirm"-button is pressed.
model = new ExcelModel
{
TriggerOnLoad = true,
TriggerOnLoadMessage = "YOU PRESSED THE CONFIRM BUTTON!",
PurchaseOrderList = null
};
return View(model);
}
}
View
@{
if (Model.TriggerOnLoad && Model.CustomOrderList != null)
{
using (Html.BeginForm("Excel", "Excel", FormMethod.Post))
{
<input id="ConfirmCustomOrder" type="submit" class="standardbutton" name="ConfirmCustomOrder" value="Confirm Custom Order" formaction="Excel" />
}
<table id="logtable">
<thead>
<tr>
<th>Order</th>
<th>Customer</th>
<th>Line</th>
<th>Product</th>
<th>Quantity</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var item in Model.CustomOrderList)
{
<tr>
<td>@Html.DisplayFor(modelItem => item.OrderNr)</td>
<td>@Html.DisplayFor(modelItem => item.Name)</td>
<td>@Html.DisplayFor(modelItem => item.Line)</td>
<td>@Html.DisplayFor(modelItem => item.ItemId)</td>
<td>@Html.DisplayFor(modelItem => item.Quantity)</td>
<td><input type="button" class="standardbutton extra-info-button" name="answer" value="Info" onclick="showDiv(@item.RowNum.ToString())" /></td>
</tr>
<tr>
<td id="@item.RowNum.ToString()" style="display: none;" class="answer_list" colspan="5">
<pre>
<strong>OrderNr:</strong> @item.OrderNr
<strong>Customer:</strong> @item.Customer
<strong>OrderLines:</strong> @item.OrderLines
// ...and a lot more fields in the model.
</pre> <br />
</td>
</tr>
}
</tbody>
</table>
}
Edit 1.