Multi HTML elements same ID in MVC - asp.net-mvc

I am generating multi Data entry Line using ASP MVC , however
looking at the HTML source after generating by MVC, I've just noticed those HTML elements has a duplicated ID , even with the same html type it is look something wrong ? is that normal behavior in MVC and how to avoid it ? , I need really to have it unique, assuming MVC should handle the ID generation for multi line, which is additional concern to me .
My code :
#foreach (var item in Model.lstMeals)
{
<tr>
<td>
<input asp-for="#item.cuisine.CuisineName" />
#Html.DisplayFor(modelItem => item.cuisine.CuisineName)
</td>
</tr>
}
then looking in HTML Source :
<tr>
<td>
<input type="text" id="item_cuisine_CuisineName" name="item.cuisine.CuisineName" value="Italian" />
Italian
</td>
</tr>
<tr>
<td>
<input type="text" id="item_cuisine_CuisineName" name="item.cuisine.CuisineName" value="French" />
French
</td>
</tr>
<tr>
<td>
<input type="text" id="item_cuisine_CuisineName" name="item.cuisine.CuisineName" value="Greek" />
Greek
</td>
</tr>

If you use tag-helper within a loop, it won't generate an unique id for you for each element It doesn't have a context of the index position within the loop.
With that said, you can easily generate your own unique id "algorithm" for your HTML elements inside the loop with usage of the index:
#for(int i = 0; i < Model.lstMeals.Count(); i++)
{
<tr>
<td>
<input asp-for="#Model.lstMeals[i].cuisine.CuisineName"
type="text"
id="xxx-xxx-lstmeals-#i" />
</td>
</tr>
}

I think you can do it with for loop something like this.
#for (int i = 0; i < Model.lstMeals.Count; i++)
{
<tr>
<td>
<input asp-for="#Model.lstMeals[i].item.cuisine.CuisineName[i]" />
#Html.DisplayFor(modelItem => item.cuisine.CuisineName)
</td>
</tr>
}

Related

How to use IsPostBack in MVC-4

I want to don't bind my dropdown list if the form state is post back. As you can see in my code I have two forms and two submit buttons. I want to keep selected value of dropdownlist after I click second submit button.
<form method="POST" action="#Url.Action("UserRoles", "PageUserRole")">
<label>Kullanıcı Grubu</label>
#Html.DropDownList("Id", Utility.GetUserGroups(), "Kullanıcı Grubu Seçiniz.")
<input type="submit" value="Listele" />
</form>
....
<form method="POST" action="#Url.Action("EditUserRoles", "PageUserRole")">
<table>
<tbody>
<tr>
<td>
İşlem
</td>
<td>
Yetki
</td>
</tr>
#for (int i = 0; i < Model.PageMenUsuserRoles.Count; i++)
{
<tr>
<td>
#Model.PageMenUsuserRoles[i].pagemenu.Name
</td>
<td>
#Html.Hidden("PageMenUsuserRoles[" + i + "].Id", Model.PageMenUsuserRoles[i].Id)
#Html.CheckBox("PageMenUsuserRoles[" + i + "].CanView", Model.PageMenUsuserRoles[i].CanView)
</td>
</tr>
}
<tr>
<td colspan="2">
<input type="submit" value="Kaydet" />
</td>
</tr>
</tbody>
</table>
</form>

How to Use/ Display a Asp.net DataList in MVC Razor View

I have this list below, which I am generating on the fly using Razor view:
<table id="contractCoverablesGrid">
<tbody>
#foreach (var coverableItem in Model.ContractCoverablesList)
{
<tr>
<td>
#Html.Hidden("coverID",coverableItem.CoverID)
</td>
<td>
#Html.Label(coverableItem.Name)
</td>
<td>
<input type='checkbox' class='chkboxActive' checked='checked' />
</td>
</tr>
}
</tbody>
</table>
As you can imagine the outcome of this is a vertical list, which keeps extending downwards.
I would like to have this list 'wrapped' into three adjacent columns instead of one single long column; just as you would do this in ASP.net Datalist server control (in Webforms).
My initial thoughts were to limit the width & height of the table to set values and then keep floating the td(s) left. But how do I float a td. I cannot turn this into div.
Any thoughts?
Please let me know.
You might try a for instead of foreach. You would loop through the list divided by 3 and start a new td each time.
This is how I resolved it:
<table id="contractCoverablesGrid" width="600" align="center">
<tbody>
<tr>
#foreach (var coverableItem in Model.ContractCoverablesList)
{
<td>
<div id="dataListItem">
#Html.Hidden("coverableID", coverableItem.CoverID)
#Html.Label(coverableItem.Name)
<input type='checkbox' name="coverableItemCheckBox" id="coverableItemCheckBox" />
</div>
</td>
}
</tr>
</tbody>
</table>
<style>
#dataListItem {
float: left;
font-weight: normal;
}
</style>

All model and Formcollection values are null, blank or don't exist in Firefox or Chrome

During debugging, my MVC model and Formcollection are blank with no values in FireFox (15) or Chrome (latest version).
During debugging using IE (9), I can see these values just fine.
Do you know what the solution is for this? This is very serious for public facing web sites not being able to do any programming angainst these browsers.
Here is my View...
#model PDFConverterModel.ViewModels.ViewModelTemplate_Guarantors
#{
ViewBag.Title = "BHG :: PDF Generator";
}
<h2>#ViewBag.Message</h2>
<div>
<table style="width: 1000px">
<tr>
<td colspan="5">
<img alt="BHG Logo" src="~/Images/logo.gif" />
</td>
</tr>
#using (Html.BeginForm("ProcessForm", "Home", FormMethod.Post))
{
<tr>
<td>
#(Html.Kendo().IntegerTextBox()
.Name("LoanID")
.Placeholder("Enter Loan ID")
)
</tr>
<tr>
<td>#Html.LabelFor(model => model.LoanType)
#Html.DisplayFor(model => model.LoanType)
</td>
<td>
<label for="ddlDept">Department:</label>
#(Html.Kendo().DropDownList()
.Name("ddlDept")
.DataTextField("DepartmentName")
.DataValueField("DepartmentID")
.Events(e => e.Change("Refresh"))
.DataSource(source =>
{
source.Read(read =>
{
read.Action("GetDepartments", "Home");
});
})
)
</td>
</tr>
if (Model.ShowGeneratePDFBtn == true)
{
if (Model.ErrorT == string.Empty)
{
<tr>
<td colspan="5">
<u><b>#Html.Label("Templates:")</b></u>
</td>
</tr>
<tr>
#for (int i = 0; i < Model.Templates.Count; i++)
{
<td>
#Html.CheckBoxFor(model => Model.Templates[i].IsChecked)
#Html.DisplayFor(model => Model.Templates[i].TemplateId)
</td>
}
</tr>
}
else
{
<tr>
<td>
<b>#Html.DisplayFor(model => Model.ErrorT)</b>
</td>
</tr>
}
if (Model.ErrorG == string.Empty)
{
<tr>
<td colspan="5">
<u><b>#Html.Label("Guarantors:")</b></u>
</td>
</tr>
<tr>
#for (int i = 0; i < Model.Guarantors.Count; i++)
{
<td>
#Html.CheckBoxFor(model => Model.Guarantors[i].isChecked)
#Html.DisplayFor(model => Model.Guarantors[i].GuarantorFirstName) #Html.DisplayFor(model => Model.Guarantors[i].GuarantorLastName)
</td>
}
</tr>
}
else
{
<tr>
<td>
<b>#Html.DisplayFor(model => Model.ErrorG)</b>
</td>
</tr>
}
}
<tr>
<td colspan="3">
<input type="submit" name="submitbutton" id="btnRefresh" value='Refresh' />
</td>
#if (Model.ShowGeneratePDFBtn == true)
{
<td>
<input type="submit" name="submitbutton" id="btnGeneratePDF" value='Generate PDF' />
</td>
}
</tr>
<tr>
<td colspan="5">
#Model.Error
</td>
</tr>
}
</table>
</div>
<script type="text/javascript">
$('btnRefresh').on('click', '#btnRefresh', function () {
Refresh();
});
function Refresh() {
var LoanID = $("#LoanID").val();
if (LoanID != "") {
document.forms[0].submit();
}
else {
alert("Please enter a LoanId");
}
}
</script>
I know this is a very old question, but answering this might help people like who are struggling with this issue.
I had a similar issue. The problem lies here:
<table style="width: 1000px">
<tr>
<td colspan="5">
<img alt="BHG Logo" src="~/Images/logo.gif" />
</td>
</tr>
#using (Html.BeginForm("ProcessForm", "Home", FormMethod.Post))
{
<tr>
<td>
#(Html.Kendo().IntegerTextBox()
.Name("LoanID")
.Placeholder("Enter Loan ID")
)
</td>
</tr>
}
</table>
After begin form there are <tr> tags directly! Browsers like chrome and mozilla get confused in such cases. The <table> tag should be inside the form. If we look at your code, which was exactly what I had done, <table> tag was before #using Html.BeginForm.
Internet Explorer somehow understands this, but the other browsers don't.
When I did an inspect element I found that there was a form tag within each <tr> tag and it always returned FormCollection as null. Simply defining <table> within form solved my problem.
So here's how it should be:
<table style="width: 1000px">
<tr>
<td colspan="5">
<img alt="BHG Logo" src="~/Images/logo.gif" />
</td>
</tr>
<tr><td>
#using (Html.BeginForm("ProcessForm", "Home", FormMethod.Post))
{
<table>
<tr>
<td>
#(Html.Kendo().IntegerTextBox()
.Name("LoanID")
.Placeholder("Enter Loan ID")
)
</td>
</tr>
</table>
}
</td></tr>
</table>
I just found out what the issue is by experimneting.
The Telerik MVC widgets don't emit any FormCollection data!!!!
Only EditorFor and TextBoxFor emit these values, plus the input buttons.
What good are these widgets if I can't use the FormCollection values from them???? Especially the DropDownList where I can retrireve data and need the selected value to pass onto other methods.
(This would be better suited as comment, but I can't comment yet)
For future reference, here's a spec (W3C might have something different) for what gets submitted when a form is submitted:
http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#category-submit
You can look at whatever HTML was generated to make sure it gets submitted. You could also use something like Fiddler to look at the Http request

Html.HiddenFor causing error

When I try to add #Html.HiddenFor(#Model.ID) to my code, I get the following error when access the page:
Compiler Error Message: CS0411: The type arguments for method 'System.Web.Mvc.Html.InputExtensions.HiddenFor(System.Web.Mvc.HtmlHelper, System.Linq.Expressions.Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
I tried reading MSDN, but the documentation is awful (they don't provide a single code example in the documentation for this method.
Here is my View:
#model CustomerService.Entity.Order
#using CustomerService.Entity
#{
ViewBag.Title = "OrderDetails";
}
<h2>
OrderDetails</h2>
#using (Html.BeginForm("HandleSubmit", "Home", FormMethod.Post))
{
<table border="1">
<tr>
<td>
<b>Order #</b>
</td>
<td>
#Model.ID
</td>
</tr>
<tr>
<td>
<b>Description</b>
</td>
<td>
#Model.Description
</td>
</tr>
<tr>
<td>
<b>Salesperson Name</b>
</td>
<td>
#Model.SalespersonName
</td>
</tr>
</table>
<h3>
Line Items</h3>
<input id="btnAddLineItem" type="submit" name="AddLineItem" value="AddLineItem" />
#Html.HiddenFor(#Model.ID)
<table border="1">
<tr>
<td>
<b>Line Item ID</b>
</td>
<td>
<b>Description</b>
</td>
</tr>
#for (int i = 0; i < #Model.LineItems.Count; ++i)
{
<tr>
<td>
#Model.LineItems[i].ID
</td>
<td>
#Model.LineItems[i].Description
</td>
</tr>
}</table>
}
HiddenFor takes an expression.
#Html.HiddenFor( model => model.ID )
HiddenFor method should get an Expression as a parameter not a value:
#Html.HiddenFor(m => m.ID)
Instead of: #Html.HiddenFor(#Model.ID)
Method signature:
HiddenFor<TModel, TProperty>(HtmlHelper<TModel>,
Expression<Func<TModel, TProperty>>)
In plain text you should give an Expression that gets an "instance" of the type of your model(in this case CustomerService.Entity.Order) and returns the desired property(in this case ID)
MSDN

MVC list of checkboxes check and select to Action then to csv file

I have a view like:
#model IEnumerable<VectorCheck.Models.Invoice>
#{
ViewBag.Title = "Exportable Invoices";
}
<script src="../../Scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="../../Scripts/jquery-ui-1.8.16.min.js" type="text/javascript"></script>
<script src="../../Scripts/Views/Export/index.js" type="text/javascript"></script
<header class="header">
<div class="headerText">
<h1>Exportable Invoices</h1>
</div>
</header>
#using (Html.BeginForm("Export", "Export")) {
<table>
<tr class="mainheader">
<th>Invoice Number</th>
<th>Date</th>
<th>Organisation</th>
<th>Total (Excl GST)</th>
<th>Status</th>
<th>Exported Date</th>
<th>
<select id="expenseSelect"></select>
<input type="submit" id="btnexport" value="Export" />
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.InvoiceNumber)
</td>
<td>
#Html.DisplayFor(modelItem => item.InvoiceDate, "{0:D}")
</td>
<td>
#Html.DisplayFor(modelItem => item.Organisation.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.TotalExcludingGst)
</td>
<td>
#Html.DisplayFor(modelItem => item.Status)
</td>
<td>
#Html.DisplayFor(modelItem => item.ExportedDateTime)
</td>
<td class="centered">
<input type="checkbox" class="exportcheckbox" data-invoiceid=#item.InvoiceId />
</td>
</tr>
}
</table>
}
<div>
#Html.ActionLink("Back to Summary", "Index", "Invoice")
</div>
Ok, so see how each checkbox has an attribrute data-invoiceid=#item.InvoiceId. Well I'm trying to get to an action method the Ids of all the invoices that have had their checkboxes checked. Also I'm trying to get the id of the selectlist expenseSelect which has options added to it on page load via jquery. I managed to achieve this with jquery and then sending the data with a $.post. The problem is in the file I'm sending the info to:
public ActionResult Export()
{
...
var csvData = _utility.GetCsvData(data);
return File(Encoding.UTF8.GetBytes(csvData), "text.csv", "invoices.csv");
}
brings up a save/open file dialog. I'm been informed this won't work for the jquery ajax call and I need to post the info back using a submit.
That's fine but now I have no idea how to send the select id and a list of the ids of the checked checkboxes to the method. Can anybody show me how to go about this?
You don't need any HTML5 data-* attributes since they are not sent to the server when you submit the form. In order to send their values you will have to use AJAX but this won't work with file downloads. So simply give your checkboxes a name:
<td class="centered">
<input type="checkbox" class="exportcheckbox" name="ids" value="#item.InvoiceId" />
</td>
and then on the server the default model binder will automatically construct an array of the ids of the checked items:
[HttpPost]
public ActionResult Export(int[] ids)
{
byte[] data = ...
return File(data, "text/csv", "invoices.csv");
}
Depending on the type of InvoiceId you might need to adjust the type of the action argument.
Radically changing my answer...
You could dynamically add a hidden IFRAME to your page. The IFRAME src can take your selected "ids" as a querystring parameter. This should get your your download dialog.
Got some help with the jquery from here: JQuery: Turn array input values into a string optimization
var selectedIdsArray = $(":checked").map(function(){return $(this).attr('data-invoiceid');});
var url = '#Url.Action("Export", "Export")?csv=' selectedIdsArray.get().join(',');
$('body').append("<iframe style='visibility:hidden' src='"+url +"'/>");

Resources