I'm current working on making a sort of wiki of plants. The first thing we started doing is the managment of the users in the site. For that we made this view that shows the results of a search from the database. The search works fine and the ViewData["datos"] returns what it should, and in this table we show the users (From the Model Usuario). In the end, for each user it should show a button that sends the Model for that user to another Controller. The problem is that the Controller receives an empty model.
Here's the code for the View. The input with the value Editar is the one that should send the model.
#model AtlasPlantasMedicinales.Models.Usuario
#{
ViewBag.Title = "Tabla";
}
#if (ViewData["datos"]!=null){
<table>
#foreach (var elemento in (List<AtlasPlantasMedicinales.Models.Usuario>)(ViewData["datos"]))
{
<tr>
<td>
#elemento.Nombre
</td>
<td>
#elemento.Carrera
</td>
<td>
#elemento.Institucion
</td>
<td>
#elemento.usuario
</td>
<td>
#elemento.correo
</td>
#using (Html.BeginForm("FormularioEditar", "Usuario", FormMethod.Post))
{
<td>#Html.HiddenFor(m => elemento) <input type="submit" value="Editar"></td>
}
</tr>
}
</table>
}
How can we send the model in elemento to the controller?
We have also tried making a Html.HiddenFor for each attribute in the model, but it still doesn't work.
Please keep in mind that me (and my teammmates) are completely new at ASP.NET MVC 4
This is a model binding problem. If you are willing to use the default model binder, use for loop instead of foreach. Your code will go something as as follows (Since you didn't post the Model/ViewModel, I will use ModelId as the property, and usuario as the value):
#for (int i = 0; i < (List<AtlasPlantasMedicinales.Models.Usuario>)(ViewData["datos"])).Count(); i++)
{
var elemento = (List<AtlasPlantasMedicinales.Models.Usuario>)(ViewData["datos"])).ElementAt(i);
<tr>
<td>
#elemento.Nombre
</td>
<td>
#elemento.Carrera
</td>
<td>
#elemento.Institucion
</td>
<td>
#elemento.usuario
</td>
<td>
#elemento.correo
</td>
#using (Html.BeginForm("FormularioEditar", "Usuario", FormMethod.Post))
{
<td>#Html.HiddenFor(m => m.ModelId, new { #Value = elemento.usuario }) <input type="submit" value="Editar"></td>
}
</tr>
}
Now, in the controller you will receive Usuario model with only the ModelId property initialized.
For more information about the model binding, I recommend you to this read this blog post by Scott Hanslman
Related
I am new to ASP.NET Core development. I am looking for something like a built-in way to use loop iteration numbers inside the view of ASP.NET Core.
I did some research and found solutions like creating int variable outside the loop and then increment inside the loop.
I want to index each user.
Here is my code:
#foreach (var item in l_IEnumerableModUserQuery)
{
<tr>
<td>
<!-- Here I want to add Iteration No. here-->
</td>
<td>
<a href="#">
#item.Pr_FullName
</a>
</td>
<td>#item.Pr_Email</td>
<td>#item.Pr_ContactNo</td>
</tr>
}
You could use a simple for loop to get the index:
//use .Count if it is a List or .Count() with Linq to get the boundary.
#for(var i = 0; i < l_IEnumerableModUserQuery.Count; i++)
{
<tr>
<td>
#i.ToString();
</td>
<td>
<a href="#">
#l_IEnumerableModUserQuery[i].Pr_FullName
</a>
</td>
<td>#l_IEnumerableModUserQuery[i].Pr_Email</td>
<td>#l_IEnumerableModUserQuery[i].Pr_ContactNo</td>
</tr>
}
Thomas Levesque has a neat approach on his blog, using an extension method:
public static IEnumerable<(T item, int index)> WithIndex<T>(this IEnumerable<T> source)
{
return source.Select((item, index) => (item, index));
}
Which would result in:
#foreach (var (item, idx) in l_IEnumerableModUserQuery.WithIndex())
{
<tr>
<td>
#idx
</td>
<td>
<a href="#">
#item.Pr_FullName
</a>
</td>
<td>#item.Pr_Email</td>
<td>#item.Pr_ContactNo</td>
</tr>
}
With an eye on the extension methods approach, you could as well amend your views model and include the index as a property in your model inside your controller / handler or whereever your model is created:
var l_IEnumerableModUserQuery =
someSource.Where(x => ...)
.Select((x, index) => new MyModel {
Index = index,
Pr_Email = xxx,
Pr_Contact = xxy,
/* ... rest of model */
});
return l_IEnumerableModUserQuery;
After this you could access the index like any other property in your view:
<a href="#">
#item.Index
</a>
you can findout the index of the item
#{
int indx=0;}
#foreach (var item in l_IEnumerableModUserQuery)
{
<tr>
<td>
#l_IEnumerableModUserQuery.IndexOf(item)
</td>
<td>
<a href="#">
#item.Pr_FullName
</a>
</td>
<td>#item.Pr_Email</td>
<td>#item.Pr_ContactNo</td>
</tr>
}
I'm a newbie and i don't know what #foreach do.
this is code written by my teacher
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.MaSach)
</td>
<td>
<img src="~/HinhAnhSP/#Html.DisplayFor(modelItem => item.AnhBia)" width="100" />
</td>
<td>
#Html.DisplayFor(modelItem => item.TenSach)
</td>
<td>
#Html.DisplayFor(modelItem=> item.GiaBan)
</td>
<td>
#Html.ActionLink("Details", "Details", new { id = item.MaSach }) |
#Html.ActionLink("Add to Cart", "Add", "Cart", new { id = item.MaSach }, new {url ="" })
</td>
</tr>
}
foreach is a construct that loops over the items of a collection (actually an enumeration, but never mind that now) and repeats whatever is inside the brackets ({,}) for each of the items, assigning a variable (named item in this case) on each iteration of the loop.
In your case, Model is a collection of items (of some type you haven't shown us). So on each iteration, it'll write all the HTML code between the brackets, assigning a variable named item on each iteration with the contents of the current item.
So imagine Model was a collection of five items of type MyType, which is defined as:
class MyType {
public string Name;
}
Where Name contains the string Hello1 in the first item, Hello2 in the second item, etc:
So if you do:
#foreach(var item in Model) {
<p>#(item.Name)</p>
}
The result once parsed will be:
<p>Hello1</p>
<p>Hello2</p>
<p>Hello3</p>
<p>Hello4</p>
<p>Hello5</p>
When I click on the column values in a table, it should redirect me to another table which has a common id, but a different view.
#foreach (var item in Model.Vendor)
{
<tr>
<td>
#Html.ActionLink(item.VendorName, "#item.Site Name", new { Id = item.VendorName})
</td>
<td>
#item.SiteCount
</td>
<td>
#item.LastReviewType
</td>
<td>
#item.LastReviewDate
</td>
<td>
#item.TeamLead
</td>
...
When I click on the vendorname values in the table, it should take me to the table which shows the sites which are assigned to the vendor.
Assuming you would have a controller by the name VendorController which has an action SiteList which would take argument venderId to generate the view, you could use
#Html.ActionLink(item.VendorName, “SiteList” /*Name of the action*/, “Vendor” /* Name of the controller */, new { venderId = item.VendorId } /* parameter */)
If the action is on the same controller which generated the first table, you may ignore /* Name of the controller argument */, thus
#Html.ActionLink(item.VendorName, “SiteList” /*Name of the action*/, new { venderId = item.VendorId } /* parameter */)
Hope this will help you
Hi I have problem with my MVC application.
I would like click on ActionLink > load data from server > and insert data to div in same page.
But my code still loads content on new page and I don`t have idea why. Anybody to help me ?
This is my Index.cshtml in HomeController,
#model IEnumerable<Kango_kmen.KangoKmenWS.WSEntityInfo>
#Content.Script("jquery-1.9.1.min.js", Url)
#Content.Script("jquery.unobtrusive-ajax.min.js",Url)
#Content.Script("jquery.unobtrusive-ajax.js",Url)
#Content.Script("myScript.js",Url)
#section Entities{
<table>
<tr>
<th>
<input type="submit" value="zobrazit" />
</th>
<th>
iD
</th>
<th>
name
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Ajax.ActionLink("..", "CheckEntity", new { id = item.iD },
new AjaxOptions{ UpdateTargetId="properties",
HttpMethod="GET",
InsertionMode=InsertionMode.InsertAfter,
})
</td>
<td>
#Html.DisplayFor(modelItem => item.iD)
</td>
<td>
#Html.DisplayFor(modelItem => item.name)
</td>
</tr>
<tr>
<td>
<div id="properties">
</div>
</td>
</tr>
}
</table>
}
#section PropertyInfo{
<p>Property info</p>
}
#section Properties{
<p>properties</p>
}
And here is my Controller in HomeController
public PartialViewResult CheckEntity(int id)
{
var model = WSConnect.getEntityInfo(id);
if(model !=null){
return PartialView("CheckEntity", model.property);
}
var modell = new WSEntityInfo[0];
return PartialView("CheckEntity", modell);
}
and ChecktEntity is the Partial view but everytime I click on ActionLink controller load url: /Home/ChceckEntity/1000 for exmaple on view data on this new page "(
There are 2 things wrong with your code:
You have included the jquery.unobtrusive-ajax.js script twice, once the minified version and once the standard version. You should include it only once
The jquery.unobtrusive-ajax.js is not compatible with jquery 1.9.1 because one of the breaking changes in jQuery 1.9 is that the .live() method was removed and the jquery.unobtrusive-ajax.js script relies on it. If you look at your javascript console you would see the following error: The .live method is undefined.. So if you want to use the unobtrusive AJAX functionality in ASP.NET MVC you will have to downgrade the version of jQuery. For example the 1.8.3 version should be fine.
So:
#model IEnumerable<Kango_kmen.KangoKmenWS.WSEntityInfo>
#Content.Script("jquery-1.8.3.min.js", Url)
#Content.Script("jquery.unobtrusive-ajax.min.js", Url)
#Content.Script("myScript.js", Url)
Also please learn how to debug your javascript code. Use a tool such as FireBug or Chrome developer toolbar where all those errors will be shown.
I am trying to render a table, using EditorFor, and a partialview, I think.
I have a model with a List<> property defined like this:
public List<TransactionSplitLine> TransactionSplitLines { get; set; }
The idea is that a user selects a few drop downs and enters a value into an edit box, and clicks a button. The model goes back to the controller, and the controller adds the entered values to the List<>
[HttpPost]
public ActionResult AccountTransaction(AccountTransactionView model)
{
var reply = CreateModel(model);
if (model.CategoryIds != null)
{
foreach (var c in model.CategoryIds)
{
reply.TransactionSplitLines.Add(new TransactionSplitLine { Amount = "100", Category = "Test Category", SubCategory = "Test More", CategoryId = int.Parse(c) });
}
}
reply.TransactionSplitLines.Add(new TransactionSplitLine { Amount = "100", Category = "Test Category", SubCategory = "Test More", CategoryId = 1 });
return View("AccountTransaction", reply);
}
Ignore the CreateModel. It simply sets up some data. Also, I am hardcoding data. This will eventually come from some form values.
The model is then returned to the same screen, allowing the user to ender more data. Any items in the List<> are read and a Table is rendered. I also have to store the current listen item values in hidden fields, so that they can be submitted back, along with the new data entered, so that the list can grow each time the user adds data.
The view is defined like this:
<table width="600">
<thead>
<tr class="headerRow">
<td>
Category
</td>
<td>
Sub Category
</td>
<td>
Amount
</td>
</tr>
</thead>
<tbody>
<%=Html.EditorFor(m=>m.TransactionSplitLines) %>
</tbody>
</table>
This is my first attempt with EditorFor...
My View is in a folder 'Views/BankAccount/AccountTransaction.aspx
I have created a ascx in Views/Shared/TransactionSplitLines.ascx
The code for the ascx is like this:
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<BudgieMoneySite.Models.TransactionSplitLine>" %>
<tr>
<td>
<%=Model.Category %>
<%=Html.HiddenFor(x => x.CategoryId)%>
</td>
<td>
<%=Model.SubCategory %>
<%=Html.HiddenFor(x => x.SubCategoryId)%>
</td>
<td>
<%=Model.Amount %>
<%=Html.HiddenFor(x => x.AmountValue)%>
</td>
</tr>
This is data
The 'This is data' is just test stuff, which is never rendered.
When I run this, all that happens is that my output is rendered as:
<table width="600">
<thead>
<tr class="headerRow">
<td>
Category
</td>
<td>
Sub Category
</td>
<td>
Amount
</td>
</tr>
</thead>
<tbody>
Test Category
</tbody>
</table>
It seems like the ascx isn't being used? I'd expect to see the 'This is data' text. But, nothing. Hopefully you can see an obvious fault?
Your editor template should be either:
~/Views/Shared/EditorTemplates/TransactionSplitLine.ascx
or:
~/Views/BankAccount/EditorTemplates/TransactionSplitLine.ascx
The name of the ascx is always the type name of the collection item (TransactionSplitLine and not TransactionSplitLines) and it should be situated at ~/Views/Shared/EditorTemplates or ~Views/ControllerName/EditorTemplates.
Or if you want to use a custom editor template name:
<%= Html.EditorFor(m=>m.TransactionSplitLines, "~/Views/foo.ascx") %>
Or use UIHintAttribute on your model.