Why the "FirstOrDefault()" is not required in the <th> rasor code? - asp.net

I'm trying to build a partial view which can add a record at the top and show the list of added items.
I have the following code. Why it's not necessary to add FirstOrDefault() in the <th> part of the html table while I had to do it in the "Add" html form? It seems FirstOrDefault() is always required since the model is IEnurable<>. However, check all the scaffold Index.cshtml files, you will find there is no FirstOrDefault() in the table head.
Is it a better way to implement one edit page for both adding and deleting actions?
#model IEnumerable<Models.MyModel>
#using (Html.BeginForm("AddItem", "MyAction", FormMethod.Post))
{
<div class="editor-label">
#Html.LabelFor(model => model.FirstOrDefault().Col1)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.FirstOrDefault().Col1)
#Html.ValidationMessageFor(m => m.FirstOrDefault().Col1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FirstOrDefault().Col2)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.FirstOrDefault().Col2)
#Html.ValidationMessageFor(m => m.FirstOrDefault().Col2)
</div>
<input type="submit" name="Submit" id="Submit" value="Add" />
}
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Col1)
</th>
<th>
#Html.DisplayNameFor(model => model.Col2)
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Col1)
</td>
<td>
#Html.DisplayFor(modelItem => item.Col2)
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { item.Col1, item.Col2})
</td>
</tr>
}
</table>
Update:
I changed it to #Html.EditorFor(m => (new Model.MyModel()).Col1) and this will not carry the value of the first row in the inserting inputs. This should be one of the solution.

You have to add FirstOrDefault because your model is IEnumerable.
So in order to get an instance you have to get one element from the IEnumerable thus, FirstOrDefault
This presents a problem though, for if the model is null, the page will throw a runtime error when trying to access that property Col1.
In the table, you are iterating over the items in the model therefore you won't need to do FirstOrDefault
I would recommend creating a model that has a property that is the instance that you're looking to bind to.
Example:
public class MyViewModel {
public MyModel MyModel { get; set; }
public IEnumerable<MyModel> MyModels { get;set; }
}
Then:
#model MyNameSpace.MyViewModel
<div class="editor-field">
#Html.EditorFor(m => m.MyModel.Col1)
#Html.ValidationMessageFor(m => m.MyModel.Col1)
</div>

You can Avoid using IEnumerable model in your View.
Model would be something like below.
public class MyModel
{
public string Col1 { get; set; }
public string Col2 { get; set; }
public string Email { get; set; }
public bool IsAdministrator { get; set; }
}
public class MyLstModel:MyModel
{
public IEnumerable<MyModel> lstMyModel { get; set; }
}
View:
#model Models.MyLstModel
#using (Html.BeginForm("AddItem", "MyAction", FormMethod.Post))
{
<div class="editor-label">
#Html.LabelFor(model => model.Col1)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.Col1)
#Html.ValidationMessageFor(m => m.Col1)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Col2)
</div>
<div class="editor-field">
#Html.EditorFor(m => m.Col2)
#Html.ValidationMessageFor(m => m.Col2)
</div>
<input type="submit" name="Submit" id="Submit" value="Add" />
}
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Email)
</th>
<th>
#Html.DisplayNameFor(model => model.IsAdministrator)
</th>
<th></th>
</tr>
#foreach (var item in Model.lstMyModel) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.Col1)
</td>
<td>
#Html.DisplayFor(modelItem => item.Col2)
</td>
<td>
#Html.ActionLink("Delete", "Delete", new { item.Col1, item.Col2})
</td>
</tr>
}
</table>

Related

How to implement Search Functionality

i create search bar in nav i want to search Member in nav bar and i have create bootstrap cards on home page
This is My Member Model
public class Member
{
[Key]
public int MemberId { get; set; }
[StringLength(60, MinimumLength = 3)]
public string? Name { get; set; }
public string? Gender { get; set; }
public DateTime DOB { get; set; }
public string? MaritalStatus { get; set; }
public string? Address { get; set; }
public long PhoneNo { get; set; }
public string? Skills { get; set; }
public string? Hobbies { get; set; }
public string? JobTitle { get; set; }
public string? Technology { get; set; }
public string? ImageName { get; set; }
public string? ImageLocation { get; set; }
public Team? Team { get; set; }
public ICollection<TeamMember>? TeamMembers { get; set; }
public ICollection<ProjectMember>? ProjectMembers { get; set; }
}
This is my View of search Bar
<form class="d-none d-md-inline-block form-inline ms-auto me-0 me-md-3 my-2 my-md-0">
<div class="input-group">
<input class="form-control" type="text" placeholder="Search for..." aria-label="Search" aria-describedby="btnNavbarSearch" />
<button class="btn btn-primary" id="btnNavbarSearch" type="button">Search</button>
</div>
</form>
I create search bar in nav I want to search Member in nav bar and I have create bootstrap cards on home page
Though your given code is not adequate to provide a complete example
for your scenario, you could implement a search option using ViewData functionality roughly by following the below steps.
How It works
By default, we will load all the members on our Index page. Because
at the beginning search key will be empty. So we have set the conditional for that. After loading all the member List now we can search. When we enter any search key it will submit the value to
the controller using ViewData["CurrentFilter"] and finally will
search into the database by that search key and return the view
back.
Controller
public IActionResult Index( string searchString)
{
ViewData["CurrentFilter"] = searchString;
var members = from mem in _context.Members
select mem;
if (!String.IsNullOrEmpty(searchString))
{
members = members.Where(m => m.Name.Contains(searchString)
|| m.Gender.Contains(searchString));
return View(members);
}
var memberList = _context.Members.ToList();
return View(memberList);
}
Note: Currently, we have implemented searching on Member Name and Gender you can extend to other properties as well by simply adding
|| or Like this way:
members = members.Where(m => m.Name.Contains(searchString)
|| m.Gender.Contains(searchString || any Other Fields));
View
#model IEnumerable<DotNet6MVCWebApp.Models.Member>
#{
ViewData["Title"] = "Index";
}
<div class="form-row">
<table>
<tr>
<td>
<a asp-action="CreateMemberView" class="btn btn-success">Create New</a>
</td>
</tr>
</table>
</div>
<table class="table">
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Gender)
</th>
<th>
#Html.DisplayNameFor(model => model.DOB)
</th>
<th>
#Html.DisplayNameFor(model => model.ImageName)
</th>
<th>
Member Details
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Gender)
</td>
<td>
#Html.DisplayFor(modelItem => item.DOB)
</td>
<td>
<img src="~/ImageName/Cover/#item.ImageName"
class="rounded-square"
height="50" width="75"
style="border:1px"
asp-append-version="true" accept="image/*" />
</td>
<td>
<a asp-action="Details" class="btn btn-primary" asp-route-memberId="#item.MemberId">Details</a> | <a asp-action="EditMember" class="btn btn-warning" asp-route-memberId="#item.MemberId">Edit</a>
</td>
</tr>
}
</tbody>
</table>
Nav Bar
<li class="nav-item">
<div class="form-row">
<table>
<tr>
<form method="get" action="/YourController/Index">
<td style="padding-right:940px">
</td>
<td>
<input class="form-control" type="text" placeholder="Search for..." name="SearchString" value="#ViewData["CurrentFilter"]" aria-label="Search" aria-describedby="btnNavbarSearch" />
</td>
<td>
<input type="submit" value="Search" class="btn btn-primary" />
</td>
</form>
</tr>
</table>
</div>
Output
If you need any further assistance on this, please see our official document here.

ASP.NET MVC Update fields of data Table at once

I have this view and I need to update the table Task upon the chosen values at Value Column View: EstimateValue. The view accepts #model IEnumerable then iterate the list of tasks and display them in Table.
The View
#model IEnumerable<Task>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<table class="table table-striped table-hover table-bordered">
<thead>
<tr class="info">
<th>
#Html.DisplayNameFor(model => model.Name)
</th>
<th>
#Html.DisplayNameFor(model => model.Description)
</th>
<th>
#Html.DisplayNameFor(model => model.Value)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
#Html.HiddenFor(modelItem => item.ID)
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
#Html.DisplayFor(modelItem => item.Description)
</td>
<td>
#Html.EditorFor(modelItem => item.Value, new { #class = "form-control" })
#Html.ValidationMessageFor(modelItem => item.Value, "", new { #class = "text-danger" })
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
The Controller has the post method EstimateValue
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EstimateValue(IEnumerable<Task> TaskList)
{
if (ModelState.IsValid)
{
foreach (var task in TaskList)
{
db.Entry(task).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Index");
}
//1. Rebound List to view
var TaskList = db.Tasks.ToList();
//2, return model to view
return View(TaskList);
}
When running the application the TaskList is null and I could not update the table Task. I have used JSON to send the data from the view as an array but still the values of TaskList are null
Change your IEnumerable to List because IEnumerable does not allow indexing. And instead of #foreach loop, use #for loop. So your View should be like this:
#model List<Task>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<table class="table table-striped table-hover table-bordered">
<thead>
<tr class="info">
<th>
#Html.DisplayNameFor(model => Model[0].Name)
</th>
<th>
#Html.DisplayNameFor(model => Model[0].Description)
</th>
<th>
#Html.DisplayNameFor(model => Model[0].Value)
</th>
</tr>
</thead>
<tbody>
#for(int i=0;i<Model.Count;i++)
{
<tr>
#Html.HiddenFor(modelItem => modelItem[i].ID)
<td>
#Html.DisplayFor(modelItem => modelItem[i].Name)
</td>
<td>
#Html.DisplayFor(modelItem => modelItem[i].Description)
</td>
<td>
#Html.EditorFor(modelItem => modelItem[i].Value, new { #class = "form-control" })
#Html.ValidationMessageFor(modelItem => modelItem[i].Value, "", new { #class = "text-danger" })
</td>
</tr>
}
</tbody>
</table>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
Then change your Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult EstimateValue(List<Task> TaskList)
{
if (ModelState.IsValid)
{
for(int i=0;i<TaskList.Count;i++)
{
db.Entry(TaskList[i]).State = EntityState.Modified;
db.SaveChanges();
}
return RedirectToAction("Index");
}
//1. Rebound List to view
var TaskList = db.Tasks.ToList();
//2, return model to view
return View(TaskList);
}
If this solves your problem, accept the answer.

post method in asp.net mvc4 goes to other page

I am working with asp.net mvc4.
I have a controller:
public class ExtendedProfileController : ProfileController
{
protected override void RegisterSystemRoutes(SanaRouteCollection routes)
{
routes.MapSystemPageRoute("Profile", "BalieNr", "BalieNr", "Profile/BalieNr");
base.RegisterSystemRoutes(routes);
}
[HttpGet]
public ActionResult Hallo()
{
return View();
}
[HttpGet]
public ActionResult BalieNr()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult BalieNr(IEntityListLoadOptions options, string accountID, ExtendedSalesAgentInfoModel model /*string accountId, ShopAccountType accountType,Customer.ICustomerListLoadOptions hallo*/)
{
var salesAgent = CommerceFramework.ShopAccounts.GetShopAccounts(options);
foreach (var item in salesAgent)
{
if (item.ShopAccountType == ShopAccountType.SalesAgent)
{
if (item.ReferenceId.Contains("DB"))
{
Console.WriteLine("true");
}
var customer = CommerceFrameworkBase.SalesPersons.GetSalesPerson(accountID);
Console.WriteLine(accountID);
}
else
Console.WriteLine("false");
}
Console.WriteLine(salesAgent);
return View();
}
}
and the method BalieNr is the main method.
So I also have a view, like this:
#{
Layout = LayoutPaths.General;
}
#model Sana.Commerce.Customization.Account.ExtendedSalesAgentInfoModel
<div class="semicolumn">
#*<div class="text">#Sana.RichText("Login_IntroductionText", makeImagesResponsive: true)</div>*#
<div class="form-holder">
#using (Html.BeginForm("BalieNr", "ExtendedProfileController", FormMethod.Post))
{
#Html.AntiForgeryToken()
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Baliecode)
</th>
<th></th>
</tr>
<tr>
<td>
#Html.TextBoxFor(modelItem => modelItem.Baliecode)
</td>
</tr>
</table>
<div class="form-row">
#*#Sana.SubmitButton("Login", "btn btn-medium btn-login")*#
<input type="submit" value="Login" />
</div>
}
</div>
<div>
</div>
</div>
So I define a action method and a controller name.
But if I do a post then it doesnt goes to my post action method in the controller - BalieNr. But it goes to this link:
http://localhost:5923/sitemap.xml
and also if I put a breakpoint on the post method BalieNr. it doesnt hit that method.
So how to solve it so that it hits the post method BalieNr?
Thank you
if I do this:
#using (Html.BeginForm("BalieNr", "ExtendedProfile", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
#Html.AntiForgeryToken()
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Baliecode)
</th>
<th></th>
</tr>
<tr>
<td>
#Html.TextBoxFor(modelItem => modelItem.Baliecode)
</td>
</tr>
</table>
<div class="form-row">
#*#Sana.SubmitButton("Login", "btn btn-medium btn-login")*#
<input type="submit" value="Login" />
</div>
}
still doesnt hit the correct method.
I have done it like this:
#{
Layout = LayoutPaths.General;
}
#model Sana.Commerce.Customization.Account.ExtendedSalesAgentInfoModel
#*#Sana.RichText("Login_IntroductionText", makeImagesResponsive: true)*#
#using (Html.BeginForm(htmlAttributes: new { #class = "form" }))
{
#Html.AntiForgeryToken()
#Html.DisplayNameFor(model => model.Baliecode)
#Html.TextBoxFor(modelItem => modelItem.Baliecode)
#*#Sana.SubmitButton("Login", "btn btn-medium btn-login")*#
}
and now it hits the post method :)
This works:
#{
Layout = LayoutPaths.General;
}
#model Sana.Commerce.Customization.Account.ExtendedSalesAgentInfoModel
<div class="semicolumn">
#*<div class="text">#Sana.RichText("Login_IntroductionText", makeImagesResponsive: true)</div>*#
<div class="form-holder">
#using (Html.BeginForm(htmlAttributes: new { #class = "form" }))
{
#Html.AntiForgeryToken()
<table>
<tr>
<th>
#Html.DisplayNameFor(model => model.Baliecode)
</th>
<th></th>
</tr>
<tr>
<td>
#Html.TextBoxFor(modelItem => modelItem.Baliecode)
</td>
</tr>
</table>
<div class="form-row">
#*#Sana.SubmitButton("Login", "btn btn-medium btn-login")*#
<input type="submit" value="Login" />
</div>
}
</div>
<div>
</div>
</div>

..NET MVC display partial view using ajax.ActionLink not working

I am using Ajax.ActionLink to send a request to my action method and update the SelectedSTRMList div with a partial view. However, the partial view is not displaying within the div when the link is clicked. I can view the partial view in a separate window. Any idea of what I am doing wrong?? In Chrome developer tools, I checked the ajax request in the Network tab and it is returning a request. I have also verified that I do have the ajax obstructive js files in ly layout view. Thanks
View
#model IEnumerable<NS.Models.FeeAuth>
<h2>Requests</h2>
<div class="table-responsive">
<table class="table table-condensed" style="border-collapse:collapse;">
<tr>
<th>
#Html.LabelFor(m => m.First().ID)
</th>
<th>
#Html.ActionLink("Request ID", "ApprovalIndex", new { sortOrder = ViewBag.RequestIDSortParam })
</th>
<th>
#Html.Label("emplid", "Student Emplid")
</th>
<th>
#Html.LabelFor(m => m.First().fname)
</th>
<th>
#Html.LabelFor(m => m.First().lname)
</th
<th></th>
</tr>
#{int i = 0;}
#foreach (var item in Model)
{
<tr data-toggle="collapse" data-parent="#collapse1_#i" data-target="#collapse1_#i" class="accordion-toggle">
<td>
#Ajax.ActionLink(Html.Encode(item.ID),
"SelectedSTRMS",
new
{
id = item.ID,
requestId = item.requestID
},
new AjaxOptions
{
UpdateTargetId = "SelectedSTRMList",
InsertionMode = InsertionMode.Replace,
HttpMethod = "GET"
})
</td>
<td>
#Html.DisplayFor(modelItem => item.requestID)
</td>
<td>
#Html.DisplayFor(modelItem => item.emplid)
</td>
<td>
#Html.DisplayFor(modelItem => item.fname)
</td>
<td>
#Html.DisplayFor(modelItem => item.lname)
</td>
</tr>
<tr>
<td colspan="6" class="hiddenRow">
<div class="accordian-body collapse" id="collapse1_#i">
<div id="SelectedSTRMList">
</div>
</div>
</td>
</tr>
i++;
}
</table>
</div>
_Layout View showing jquery
<script src="#Url.Content("~/Scripts/jquery-1.11.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery-ui-1.11.2.min.js")" type="text/javascript"></script>
#*<script src="#Url.Content("//ajax.aspnetcdn.com/ajax/mvc/3.0/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>*#
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
Partial View
<table>
<tr>
<td>
<ul>
#foreach (var s in (List<string>)ViewBag.SemesterInfo)
{
<li style="padding-bottom:20px;">#s</li>
}
</ul>
</td>
</tr>
</table>
Controller
public PartialViewResult SelectedSTRMS(int id, int requestId)
{
FeeAuthWithCommentsViewModel feeauth = new FeeAuthWithCommentsViewModel();
feeauth.FeeAuth = db.FeeAuths.Find(id);
int feeauthID = id;
List<string> GetSTRM = new List<string>();
GetSTRM = db.vw_GetSTRMs.Where(v => v.FeeAuthID == feeauthID).Select(v => v.DESCR).ToList();
if (GetSTRM.Count > 0)
{
ViewBag.SemesterInfo = GetSTRM.ToList();
}
else
{
ViewBag.SemesterInfo = new List<string> { "No STRM Selected" };
}
return PartialView("_SelectedSTRMS");
}

Html rendering order for asp mvc

How come my form loads like this?
Here is my code :
#using MvcApplication6.Models;
#model List<Employee>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
Create Entry
</p>
<p>#Html.ActionLink("Check departments", "Index", "Department")</p>
<p>Check summary</p>
<table border="1">
<tr>
<th>
#Html.DisplayNameFor(model => model[0].id)
</th>
<th>
#Html.LabelFor(model => model[0].firstname)
</th>
<th>
#Html.LabelFor(model => model[0].lastname)
</th>
<th>
#Html.DisplayNameFor(model => model[0].gender)
</th>
<th>
#Html.DisplayNameFor(model => model[0].department)
</th>
<th>Action</th>
</tr>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
foreach (Employee mod in Model)
{
<tr>
<td>
<input type="hidden" value="#mod.id" name="id" id="id" />
#Html.DisplayFor(modelItem => mod.id)
</td>
<td>
#Html.DisplayFor(modelItem => mod.firstname)
</td>
<td>
#Html.DisplayFor(modelItem => mod.lastname)
</td>
<td>
#Html.DisplayFor(modelItem => mod.gender)
</td>
<td>
#Html.DisplayFor(modelItem => mod.department)
</td>
<td>
<button onclick="location.href='#Url.Action("Edit", new { id = mod.id })';return false;">Edit</button>
#Html.CheckBoxFor(modelItem => mod.selected)
</td>
</tr>
}
<br />
<input type="submit" value="submit" />
}
</table>
Here are my concerns:
Notice that i put my submit button after the foreach loop but how come it was rendered first before the actual boxes?
I've been trying to put it on the bottom but i am having some problems.
What's the ordering for render?

Resources