C# ASP.NET MVC Table rows as form values FormCollection - c#

I'm stuck with getting values out of the FormCollection in my controller. The problem is that my form is a table.
<% using (Html.BeginForm("PasOverlappendeAfwezighedenAan", "Afwezigheid")) {%>
<table>
<tr>
<th></th>
<th>
datumVan
</th>
<th>
datumTot
</th>
<th>
beginUur
</th>
<th>
eindUur
</th>
<th>
reden
</th>
</tr>
<% foreach (var item in Model.Afwezigheden)
{ %>
<tr>
<td>
<input type="text" name="datumVan" id="datumVan" value="<%: String.Format("{0:g}", item.datumVan) %>" />
</td>
<td>
<input type="text" name="datumTot" id="Text1" value="<%: String.Format("{0:g}", item.datumTot) %>" />
</td>
<td>
<input type="text" name="beginUur" id="Text2" value="<%: item.beginUur %>" />
</td>
<td>
<input type="text" name="eindUur" id="Text3" value="<%: item.eindUur %>" />
</td>
<td>
<input type="text" name="reden" id="Text4" value="<%: item.reden %>" />
</td>
</tr>
<% } %>
</table>
<% } %>
So the Controller should turn each row from the table into an object.
public ActionResult PasOverlappendeAfwezighedenAan(FormCollection fc, Student stud){
}
But how would I get a row or the data for one row out of the FormCollection?
Thanks in advance,
Me
ps: sorry for the dutch names in the codes

sure we can use the form colleciton like:
public ActionResult Test2(FormCollection postback)
{
var i = postback["beginUur"];
var j = postback["eindUur"];
return View();
}
then the value of i will be a string like: "20,40,60" if our post form has 3 fields(or called [input text]) is named "beginUur".. and we can use
string [] beginUurResult = i.Split(',');
to get the string array of each beginUur value
--
or each field be a single List like:
public ActionResult PasOverlappendeAfwezighedenAan(List<string> datumVan, List<string> datumTot){
}

Related

Can a Form POST be too large for MVC Model Binder

This problem occurs in .net core 3.1 MVC website.
I am having trouble getting my POST to bind to my controller action (the parameter always comes through as null). The data is loaded from a database, and is a large recursive structure.
If I delete a few hundred lines of the JSON (out of 2500 or so) in the database it will bind OK.
The GET displays perfectly.
Even when I change my Action method parameter from my ViewModel to IFormCollection, it still comes through as null. Is there some limit here that I wasn't aware of?
If the size is the issue, is there a better approach for POSTing the data?
Parent View
<form id="frmAdditionalCodes" name="frmAdditionalCodes" method="post">
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Code)
</th>
<th>
#Html.DisplayNameFor(model => model.FullName)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td style="width:50px">
#Html.DisplayFor(modelItem => Model.Code)
<input asp-for="#Model.Code" class="form-control" style="display:none" />
</td>
<td style="width:50px">
#Html.DisplayFor(modelItem => Model.FullName)
<input asp-for="#Model.FullName" class="form-control" style="display:none" />
</td>
<td style="width:50px">
#Html.DisplayFor(modelItem => Model.Description)
<input asp-for="#Model.Description" class="form-control" style="display:none" />
</td>
<td style="width:20px">
<span>
<i id="addTagItem" class="fas fa-folder-plus" title="Add child item"></i>
</span>
</td>
<td>
<partial name="~/Views/PartialViews/_SectionsAndTags.cshtml" model="#Model.Entities" view-data="ViewData" />
</td>
<td>
</td>
</tr>
</tbody>
</table>
</form>
Child View
<table class="partial_table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Code)
</th>
<th>
#Html.DisplayNameFor(model => model.FullName)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th colspan="2">
#Html.DisplayNameFor(model => model.Entities)
</th>
</tr>
</thead>
<tbody>
#{ List<CdsDeclarationSectionAndTagItemViewModel> list = Model.ToList();
for (int i = 0; i < list.Count(); i++)
{
<tr>
#{
string elementNameCode = $"{list[i].Prefix}Code";
string elementNameFullName = $"{list[i].Prefix}FullName";
string elementNameDescription = $"{list[i].Prefix}Description";
string elementNameIsDeleted = $"{list[i].Prefix}IsDeleted";
}
<td>
<span>#list[i].Code</span>
<input asp-for="#list[i].Code" name="#elementNameCode" class="form-control" style="display: none" />
</td>
<td>
<span>#list[i].FullName</span>
<input asp-for="#list[i].FullName" class="form-control" name="#elementNameFullName" style="display: none" />
</td>
<td>
<span>#list[i].Description</span>
<input asp-for="#list[i].Description" class="form-control" name="#elementNameDescription" style="display: none" />
</td>
<td>
#if (list[i].Entities?.Length > 0)
{<img id="collapseItem" state="expanded" width="20" height="20" src="~/images/minus_PNG24.png" />
}
<span>
<i id="editTagItem" class="fas fa-pencil-alt" title="Edit item"></i>
<i id="deleteTagItem" class="far fa-trash-alt" title="Delete item"></i>
<i id="addTagItem" class="fas fa-folder-plus" title="Add child item"></i>
<i id="updateTagItem" class="far fa-save" title="Save changes" style="display: none"></i>
<i id="cancelTagItem" class="fas fa-undo-alt" title="Undo changes" style="display: none"></i>
</span>
</td>
<td>
#if (list[i].Entities?.Length > 0)
{
<partial name="~/Views/PartialViews/_SectionsAndTags.cshtml" model="#list[i].Entities" />
}
</td>
<td>
<input type="hidden" value="false" name="#elementNameIsDeleted" />
</td>
</tr>
}
}
</tbody>
</table>
ViewModel
public class CdsDeclarationSectionAndTagViewModel
{
public string Code { get; set; }
public string FullName { get; set; }
public string Description { get; set; }
public CdsDeclarationSectionAndTagItemViewModel[] Entities { get; set; }
}
public class CdsDeclarationSectionAndTagItemViewModel
{
public string Code { get; set; }
public string FullName { get; set; }
public string Description { get; set; }
public CdsDeclarationSectionAndTagItemViewModel[] Entities { get; set; }
public string Prefix { get; set; }
public bool IsDeleted { get; set; }
}
Controller
Here vm is null unless I remove some data
[HttpPost]
public async Task<IActionResult> CdsDeclarationSectionAndTag(CdsDeclarationSectionAndTagViewModel vm)
{
}
If I change it like so, fc is also null
[HttpPost]
public async Task<IActionResult> CdsDeclarationSectionAndTag(IFormCollection fc)
{
}
The posted Form Data looks like this (and can end up with 4 or 5 recursive levels)
Code: 42A
FullName:
Description: Declaration
Entities[0].Code: 023
Entities[0].FullName: Acceptance (taxpoint) datetime
Entities[0].Description: Acceptance (taxpoint) datetime
Entities[0].IsDeleted: false
Entities[1].Code: D026
Entities[1].FullName: LRN
Entities[1].Description: LRN
Entities[1].IsDeleted: false
Entities[2].Code: D013
Entities[2].FullName: Declaration type
Entities[2].Description: Declaration type
Entities[2].IsDeleted: false
Entities[3].Code: 109
Entities[3].FullName: Invoice total
Entities[3].Description: Invoice total
Entities[3].IsDeleted: false
Entities[4].Code: 504
Entities[4].FullName: Specific circumstances indicator
Entities[4].Description: Specific circumstances indicator
Entities[4].IsDeleted: false
Entities[5].Code: 131
Entities[5].FullName: Gross mass
Entities[5].Description: Gross mass
Entities[5].IsDeleted: false
Entities[6].Code: 146
Entities[6].FullName: Total packages
Entities[6].Description: Total packages
Entities[6].IsDeleted: false
Entities[7].Code: 61B
Entities[7].FullName: Authentication
Entities[7].Description: Authentication
Entities[7].Entities[0].Code: 104
Entities[7].Entities[0].FullName: Signature/Authentication
Entities[7].Entities[0].Description: Signature/Authentication
Entities[7].Entities[0].IsDeleted: false
Entities[7].IsDeleted: false
Entities[8].Code: 02A
Entities[8].FullName: Deferred Payment
Entities[8].Description: Deferred Payment
Entities[8].Entities[0].Code: D031
Entities[8].Entities[0].FullName: Deferment category code
Entities[8].Entities[0].Description: Category code
Entities[8].Entities[0].IsDeleted: false
Entities[8].Entities[1].Code: D005
Entities[8].Entities[1].FullName: Deferment ID
Entities[8].Entities[1].Description: ID
Entities[8].Entities[1].IsDeleted: false
Entities[8].Entities[2].Code: D006
Entities[8].Entities[2].FullName: Deferment Type
Entities[8].Entities[2].Description: Type
Entities[8].Entities[2].IsDeleted: false
Entities[8].IsDeleted: false
Entities[9].Code: 03A
Entities[9].FullName: Additional Information
Entities[9].Description: Additional Information
Entities[9].Entities[0].Code: 226
Entities[9].Entities[0].FullName: Additional Information Statement code
Entities[9].Entities[0].Description: Statement code
Entities[9].Entities[0].IsDeleted: false
....
I found the answer on this thread.
It turns out that by default, there is a limit of 1024 on Form Values that you can submit.
I used the following code in Startup.cs to change the limit and the problem has gone away, and can now bind successfully
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
});

MVC submit button is always submitting the first record details on POST

I have a foreach loop in MVC page. like below. But, when I am submitting the form using submit button, it is always submitting the first record. Unable to understand why it is doing that way. Appreciate the help.
#model IEnumerable<DeployModel>
#using (Html.BeginForm("Index", "Dep", FormMethod.Post))
{
<div class="col-md-11">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-body" id="modal-body" style="overflow-y: auto">
#if (Model != null && Model.Any())
{
<div>
<table class="table table-condensed table-hover table-bordered">
<thead>
<th>
S1 Name
</th>
<th>
S2 Name
</th>
<th>
Old Version
</th>
<th>
New Version
</th>
<th>
Status
</th>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(o => item.S1)
</td>
<td>
#Html.DisplayFor(o => item.S2)
</td>
<td>
#Html.DisplayFor(o => item.OldVersion)
</td>
<td>
#Html.DisplayFor(o => item.NewVersion)
</td>
<td>
#Html.DisplayFor(o => item.Status)
</td>
<td>
<button name="SubmitButton" class="btn action-btn" type="submit" > Submit </button>
</td>
</tr>
}
</tbody>
</table>
</div>
}
</div>
</div>
</div>
</div>
}
My Controller action looks like as, but it is always receiving first record irrespective of button click.
[HttpPost]
public ActionResult Index(DeployModel deployModel)
{
//TODO code
}
Any idea how to resolve this?
There are a couple of problems here. The first is that Html.DisplayFor will just write the display string for the selected property's value with nothing telling the browser that it is form data to be submitted. The other is that all of your submit buttons are for the same form. There are a few ways to solve these problems. The one I would suggest is to create a separate form for each instance of DeployModel, and create hidden inputs for each property you are expecting to receive upon submission of the form:
// inside your foreach loop
#using (Html.BeginForm("Index", "Dep", FormMethod.Post))
{
<input type="hidden" name="S1" value="#item.S1" />
<input type="hidden" name="S2" value="#item.S2" />
...
<input type="submit" value="Submit" />
}
Also please note that if you use this method you should remove the outer form - you don't want nested forms!
You have to give a diffrent Name for each input.
exmaple
#Html.DisplayFor(o => item.S1, new { name = "input1" })

how to update a raw within a partial view in MVC C#

i have a web application where i need to update the rows of a table one by one inside a partial view. the problem i'm facing now is how can i insert the update inside the partial view method in the controller. i'm using visual studio 2013 toad for oracle
The partial view
<table>
<thead>
<tr>
<th style="display:none;"> ProID </th>
<th> Requeser Name </th>
<th> Project Name </th>
<th> Supervisor Name </th>
<th> Description </th>
<th> Start Date </th>
<th> Due Date </th>
<th> Status </th>
<th> Done </th>
</tr>
</thead>
<tbody>
<tr>
#foreach (var items in Model)
{
<td>#items.USERID</td>
}
<td>
<input type="text" id="txt_pname" />
</td>
<td>
<input type="text" id="txt_sname" />
</td>
<td>
<input type="text" id="txt_dname" />
</td>
<td> <input name="text_stdate" id="iDate" class="form-control" readonly>
<span class="input-group-btn">
<button class="btn default" type="button"><i class="fa fa-calendar"></i></button>
</span></td>
<td>
<input name="text_dudate" id="iDate" class="form-control" readonly>
<span class="input-group-btn">
<button class="btn default" type="button"><i class="fa fa-calendar"></i></button>
</span>
</td>
<td>
<input type="text" id="txt_dname" />
</td>
<td>
<select id="txt_stat">
<option>Pending</option>
<option>Open</option>
<option>Close</option>
<option>Cancle</option>
</select>
</td>
</tr>
#foreach (var items in Model)
{
<td>
<a onclick="update_Row('#items.PROJECTT', '#items.IDP');" class="edit" href="#"> Done </a>
</td>
}
</table>
<table class="" id="sample_editable_1">
<thead>
<tr>
<th style="display:none;"> ProID </th>
<th> Requeser Name </th>
<th> Project Name </th>
<th> Supervisor Name </th>
<th> Description </th>
<th> Start Date </th>
<th> Due Date </th>
<th> Status </th>
<th> Edit </th>
</tr>
</thead>
<tbody>
#foreach (var items in Model)
{
<tr>
<td style="display:none;"> #items.IDP</td>
<td>#items.USERID</td>
<td>#items.PROJECTT</td>
<td>#items.PROJSUP</td>
<td>#items.PROJDES</td>
<td>#items.STARTDT</td>
<td>#items.DUEDT</td>
<td>#items.SCONDITION</td>
<td>
<a onclick="update_Row('#items.PROJECTT', '#items.IDP');" class="edit" href="#"> Edit </a>
</td>
</tr>
}
</tbody>
</table>
the controller
public ActionResult viewstat(string id)
{
List<mdlProject> itemList = new List<mdlProject>();
try
{
dbconn.openConnection();
strSQL = #"select ID,PROJTTL,PROJSVSOR,PROJDES,STARTDT,DUEDT,USERID,S_CONDITION from
PR_TBLPROJECT
inner join PR_TBLSTATUS on pr_tblstatus.s_id=PR_TBLPROJECT.id
where PR_TBLPROJECT.id=:id";
cmd = new OracleCommand(strSQL, dbconn.DbConn);
cmd.Parameters.Add("PROJTTL", OracleDbType.Varchar2, id, ParameterDirection.Input);
OracleDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
itemList.Add(new mdlProject
{
PROJECTT = dr["PROJTTL"].ToString(),
PROJSUP = dr["PROJSVSOR"].ToString(),
PROJDES = dr["PROJDES"].ToString(),
STARTDT = Convert.ToDateTime(dr["STARTDT"].ToString()).ToString("dd-MM-yyyy"),
DUEDT = Convert.ToDateTime(dr["DUEDT"].ToString()).ToString("dd-MM-yyyy"),
USERID = dr["USERID"].ToString(),
SCONDITION = dr["S_condition"].ToString(),
IDP = dr["ID"].ToString(),
//SID = dr["S_ID"].ToString(),
ACTV = "",
});
}
}
dr.Dispose();
cmd.Dispose();
}
finally
{
dbconn.closeConnection();
}
return PartialView(itemList);
}
Not sure what exact error you are getting but approach will be On click of each anchor tag, call a javascript method and from that javascipt method send a ajax request to update the row and then call your partial view method viewstat to refresh the table.

C# MVC4 table with multiple submit buttons - always sends the same data

I have a table inside my view that lists case details in each row. Every row has a submit button called "View Details". I have two hidden fields, TicketNumber and CaseId that are submitted when the user clicks the "View Details" button.
The problem is: it always sends the TicketNumber and CaseId of the first case in the table no matter which "View Details" button is pressed.
Here is the code of the view:
#model IEnumerable<Models.Case>
#{
ViewBag.Title = "AbandonedVehiclesLandingPage";
}
<h2>AbandonedVehiclesLandingPage</h2>
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.TicketNumber)
</th>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.Status)
</th>
<th>
#Html.DisplayNameFor(model => model.SubmittedOn)
</th>
<th></th>
</tr>
</table>
#using (Html.BeginForm("ViewCase", "Home",FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<table>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.TicketNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.SubmittedOn)
</td>
<td>
<input type="hidden" value="#item.TicketNumber" name="TicketNumber" />
<input type="hidden" value="#item.CaseId" name="CaseId" />
<input type="submit" value="View Details" />
</td>
</tr>
}
</table>
}
Here is the receiving Action:
[HttpPost]
public ActionResult ViewCase(string TicketNumber, string CaseId)
{
string token = (string)Session["token"];
if(token!=null)
{
if (provider.ValidateUser(Session["token"].ToString(), ""))
{
CaseService service = new CaseService("");
CaseNote caseInfo = service.fetchSingleCase(TicketNumber, CaseId);
return View("ViewCase", caseInfo);
}
}
return Redirect(HttpContext.Application["connectUrl"].ToString()
+ HttpContext.Application["redirectUrl"].ToString());
}
Last thing to say, it worked up until the point I lost the original View code and had to re-write it again. It feels like something small I am missing here.
Change your table as follows:
<table>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.TicketNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.SubmittedOn)
</td>
<td>
#using (Html.BeginForm("ViewCase", "Home",FormMethod.Post))
{
#Html.AntiForgeryToken()
<input type="hidden" value="#item.TicketNumber" name="TicketNumber" />
<input type="hidden" value="#item.CaseId" name="CaseId" />
<input type="submit" value="View Details" />
}
</td>
</tr>
}
</table>

Create a view inside a view on submit MVC4

I have a view with a form, when that form is submitted I want to show another view inside the first view. I have tried with partialview (not sure that is for my purpose?) but I cant get it to work because the model is null (its strongly-typed partialview). But I just want it to be created on the submitbutton and then it should be OK.
So, help my create a view/partialview inside a when submitting my form. Right now I get "Object reference not set to an instance of an object." on the foreach loop in my partial view, but it's not supposed to be created until the form is submitted.
My view:
<div class="calcInput">
#using (Html.BeginForm("ShowDetail", "Calculation"))
{
<div class="calculateBox">
<label for="calcOption">Choose value to calculate:</label>
<select form="anFormCalcInput" id="calcOption" title="Choose what value you want to calculate">
<option value="anPMT">Payment (PMT)</option>
<option value="anI">Interest (I)</option>
<option value="anFV">Future value (FV)</option>
<option value="anPV">Present value (PV)</option>
</select>
</div>
<div class="calculateBox" background-color="#777777">
#Html.Label("Present value (PV)")
#Html.TextBox("PresentValue")
#Html.Label("Future value")
#Html.TextBox("FutureValue")
#Html.Label("Interest rate")
#Html.TextBox("InterestRate") <br />
<input type="radio" name="advanceOrArrears" id="inAdvance" value="inAdvance" /> In advance<br />
<input type="radio" name="advanceOrArrears" id="inArrears" value="inArrears" /> In arrears
</div>
<div class="calculateBox">
<label for="startDate">Start date:</label>
<input type="date" id="anStartDate" name="startdate" title="Choose start date for your calculation" /><br />
#Html.Label("Payment frequency")
<select form="anFormCalcInput" id="anPmtFreq" title="Choose the payment frequency, for example: Every month">
<option value="Monthly">Monthly</option>
<option value="Quarterly">Quarterly</option>
<option value="Yearly">Yearly</option>
</select><br /><br />
#Html.Label("No of payment periods")
#Html.TextBox("PaymentPeriods")
#Html.Label("Date time convention")
<select form="anFormCalcInput" id="anDTC" title="Choose your Date time convention">
<option value="360360">360/360</option>
<option value="365365">365/365</option>
</select><br /><br />
<input type="submit" id="anCalcBtn" class="calcBtn" name="anSubmitBtn" value="Calculate" title="Calculate your calculation" />
</div>
}
</div>
<table cellspacing="0" width="80%">
<div class="calcGraph">
</div>
<div class="calcDetail" id="anCalcDetail">
#Html.Partial("ShowDetail") //This is where I want my view/partialview to show up
</div>
My partialview:
#model IEnumerable<CalcFactory.Models.Calculation>
<table cellspacing="0" width="80%">
<thead>
<tr>
<th>
Date
</th>
<th>
Invoice amount
</th>
<th>
Interest rate
</th>
<th>
Interest amount
</th>
<th>
Amortization
</th>
<th>
Capital balance
</th>
<th></th>
</tr>
</thead>
<tr>
<td align="center">
</td>
<td align="center">
</td>
<td align="center">
</td>
<td align="center">
</td>
<td align="center">
</td>
<td align="center" id="startValue">
</td>
</tr>
#foreach (var item in Model) { //this is where i get null exception, model is null. But it supposed to be created on submit button...
<tr>
<td>
#Html.DisplayFor(modelItem => item.Date)
</td>
<td>
#Html.DisplayFor(modelItem => item.InvoiceAmount)
</td>
<td>
#Html.DisplayFor(modelItem => item.InterestRate)
</td>
<td>
#Html.DisplayFor(modelItem => item.InterestAmount)
</td>
<td>
#Html.DisplayFor(modelItem => item.Amortization)
</td>
<td>
#Html.DisplayFor(modelItem => item.PresentValue)
</td>
</tr>
}
My Controller:
public class CalculationController : Controller
{
public PartialViewResult ShowDetail(FormCollection form)
{
List<Calculation> cList = new List<Calculation>();
Calculation calc = new Calculation();
calc.Date = Convert.ToDateTime(form["startdate"]);
calc.InvoiceAmount = 2000;
calc.InterestRate = Convert.ToDouble(form["InterestRate"]);
calc.InterestAmount = (Convert.ToDouble(form["PresentValue"]) * Convert.ToDouble(form["InterestRate"]) / 360 * 30);
calc.Amortization = (2000 - (Convert.ToDouble(form["PresentValue"]) * Convert.ToDouble(form["InterestRate"]) / 360 * 30));
calc.PresentValue = Convert.ToDouble(form["PresentValue"]) - calc.Amortization;
cList.Add(calc);
for (int i = 0; i < Convert.ToInt32(form["PaymentPeriods"]); i++)
{
Calculation calcBefore = cList.Last();
calc = new Calculation();
calc.Date = calcBefore.Date.AddMonths(1);
calc.InvoiceAmount = 2000;
calc.InterestRate = Convert.ToDouble(form["InterestRate"]);
calc.InterestAmount = (calcBefore.PresentValue * Convert.ToDouble(form["InterestRate"]) / 360 * 30);
calc.Amortization = (calc.InvoiceAmount - (calcBefore.PresentValue * calc.InterestRate / 360 * 30));
calc.PresentValue = calcBefore.PresentValue - calc.Amortization;
cList.Add(calc);
}
return PartialView("ShowDetail", cList);
}
}

Categories