I'm working with ASP.Net MVC with SQL server management studio.
Now how would I get a record by a given name and/or id?
Currently, I only find a record using the id which just works fine, but when searching a record by name, it won't find the correct record.
My current code looks something like this:
//Student.cs
public partial class Student
{
public int No { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public Nullable<decimal> mobileno { get; set; }
public string Image { get; set; }
}
//Index.cshtml
#using (Html.BeginForm("search", "CrudManually", FormMethod.Post))
{
#Html.TextBox("id")<br/>
#Html.TextBox("searchString")<br/>
<input type="submit" value="Search"/>
}
//CrudManuallyController.cs
public class CrudManuallyController : Controller
{
public ActionResult Index()
{
return View(db.manages.ToList());
//return View();
}
[HttpPost]
public ActionResult search(int id,string searchString,Student students)
{
var query = db.students.Where(d => d.No == id).AsQueryable();
if (!string.IsNullOrEmpty(searchString))
{
query = query.Where(d => d.Name.Contains(searchs)); // generate an error local variable 'searchs' before it is declared.
}
var searchs = query.ToList();
return View("index",searchs);
}
}
Now how would I query for an id and a name at the same time?
update your controller
public class CrudManuallyController : Controller
{
public ActionResult Index()
{
return View(db.manages.ToList());
//return View();
}
[HttpPost]
public ActionResult search(int? id, string searchString,Student students)
{
//Lambda Linq to entity does not support Int32
//var search = (from d in db.students where d.No == Convert.ToInt32(id) && d.Name == id select d).ToList();
//var search = db.students.Where(d => d.No == Convert.ToInt32(id) && d.Name == id).ToList();
query = db.students.AsQueryable();
if (id.HasValue)
{
var studentId = id.Value;
query = query.Where(d => d.No == studentId);
}
if (!string.IsNullOrEmpty(searchString))
query = query.Where(d => d.Name.Contains(searchString));
var search = query.ToList();
return View("index",search);
}
}
update your .cshtml
#using (Html.BeginForm("search", "CrudManually", FormMethod.Post))
{
#Html.TextBox("id")
#Html.TextBox("searchString")
<br/>
<input type="submit" value="Search"/>
}
You can get 2 way
list.Where(i => i.Property == value).FirstOrDefault(); // C# 3.0+
list.Find(i => i.Property == value); // C# 3.0+
if you find any item, you can get that. If you dont find an item, you get null.
Tell me if you resolve :)
Related
I am trying to populate a drop-down list. Initially, everything runs as I expect it to. But, when I navigate away from the original view and come back, I get this error:
System.NullReferenceException: 'Object reference not set to an
instance of an object.' System.Web.Mvc.WebViewPage.Model.get
returned null.
I tried adding an if statement to account for a null model but that did not work. (I took it out for now)
Thank you in advance.
Model:
public class IndexDates
{
public List<PeriodEndDates> ListForDropDown { get; set; }
}
Controller:
public ActionResult Index(IndexDates datesParam)
{
using (PayrollEntities2 db = new PayrollEntities2())
{
DateTime todaysDate = DateTime.Now;
var model = new IndexDates()
{
ListForDropDown = db.PeriodEndDates2
.Where(x => x.periodEndDate <= todaysDate)
.OrderByDescending(x => x.periodEndDate )
.ToList()
};
return View(model);
}
}
View:
#using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
<div class="schedule-bottom">
<p>Period End Date: #Html.DropDownListFor(model => model.ListForDropDown, new SelectList(Model.ListForDropDown, "periodEndDate", "periodEndDate"), "Select...", new { onChange = "selectedtext(this)" })</p>
</div>
}
PayrollEntities2:
public partial class PayrollEntities2 : DbContext
{
public PayrollEntities2()
: base("name=PayrollEntities2")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
throw new UnintentionalCodeFirstException();
}
public virtual DbSet<PeriodEndDates2> PeriodEndDates2 { get; set; }
}
Home Controller Redirect:
[HttpPost]
public ActionResult Authorize(UsersAndDates userModel)
{
using (MasterTable db = new MasterTable())
{
var userDetails = db.PaybillUsers.Where(x => x.userName == userModel.userName && x.password == userModel.password).FirstOrDefault();
var datesToDisplay = db.PeriodEndDates2
.Where(x => x.ffsPayDate > DateTime.Now)
.Select(x => new PayDates
{
PayDate = x.ffsPayDate,
PeriodEndDate = x.periodEndDate
})
.FirstOrDefault();
if (userDetails == null)
{
return View("Login", userModel);
}
else
{
Session["userID"] = userDetails.userName.ToString();
Session["payDate"] = datesToDisplay.PayDate.ToString();
Session["endDate"] = datesToDisplay.PeriodEndDate.ToString();
return RedirectToAction("Index", "Dashboard");
}
}
}
I think it's because you use using (PayrollEntities2 db = new PayrollEntities2())
instead of just declaring it.
Need to create the edit View with selected Checkboxes from createView
public class CustomerTypeViewModel
{
[Required]
public int? Id { get; set; }
public string Description { get; set; }
[Display(Name = "Please select the Type")]
public bool Selected { get; set; }
}
CustomerView when i should load a list of CustomerTypeViewModel
public List<CustomerTypeViewModel> SelectedCustomerTypes { get; set; }
private List<CustomerTypeViewModel> selectionList = new List<CustomerTypeViewModel>();
public CustomerViewModel()
{
SelectedCustomerTypes = new List<CustomerTypeViewModel>();
}
public void SetCustomerTypeViewModel(IEnumerable<CustomerTypeViewModel> selected, IEnumerable<CustomerTypeViewModel> all)
{
SelectedCustomerTypes.Clear();
foreach (var item in all)
{
SelectedCustomerTypes.Add(item);
}
foreach (var item in selected)
{
SelectedCustomerTypes.FirstOrDefault(x => x.Description == item.Description).Selected = true;
}
}
public List<CustomerTypeViewModel> GetTipi()
{
return selectionList;
}
In controller i should call a method that get customertypes from manager
public CustomerTypeViewModel GetCustomerType(int? customerId)
{
var query = "SELECT * FROM CustomerType where Id = #Id";
return context.GetObject<CustomerTypeViewModel>(query, new { Id = customerId });
}
Now in the Edit at the Controller
[AuthorizeRoles(RoleNames.CanEditCustomer)]
public ActionResult Edit(int? id, int? customerId)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var customer = customerManager.Get(customerId);
var vm = new CustomerViewModel();
vm.SetCustomerTypeViewModel(new List<CustomerTypeViewModel>(), customerTypeManager.GetAll());
if (customer == null)
{
return HttpNotFound();
}
return View(customer);
}
I was told to create a method in manager GetCustomerType(customerId)
<-- this is the id from db table where checkboxes are saved and this method load a list of CustomerTypeViewModel
Now Edit View
<div class="form-group">
#{
for (int i = 0; i < Model.SelectedCustomerTypes.Count(); i++)
{
<div class="col-md-10">
#Html.Label(Model.SelectedCustomerTypes[i].Description, new { #class = "control-label col-md-2" })
#Html.CheckBoxFor(model => model.SelectedCustomerTypes[i].Selected, new { #checked = "checked" })
#Html.HiddenFor(model => model.SelectedCustomerTypes[i].Id, new { data_val = false })
#Html.HiddenFor(model => model.SelectedCustomerTypes[i].Description, new { data_val = false })
</div>
}
}
</div>
You need to fix the GetCustomerType method in your controller. Try this:
public IActionResult GetCostumerType(int? id)
{
if (id == null)
{
return NotFound();
}
var test = from custom in _yourContext.CustomerType
.Where(p => p.CustomerType.Id == customerId)
select custom;
//change _yourContext with your context variable
if (test == null)
{
return NotFound();
}
return View(test);
}
This way you are getting the custom types associated with the id passed in the method.
I have a simple select with an option selected from the model that is loaded.
To start here is my simple model
public class invoice
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public invoice_state invoice_state { get; set; }
}
public class invoice_state
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public string alias { get; set; }
public List<invoice> invoices { get; set; }
[Display(Name = "title")]
public string title { get; set; }
}
Here is what I have that works in one view.
in controller:
public IActionResult Create()
{
string state = "start_finish";
ViewBag.State = state;
var states = _context.invoice_state.Select(c => new {
id = c.ID,
title = c.title
}).ToList();
ViewBag.States = new SelectList(states, "id", "title", _context.invoice_state.Where(e => e.alias == state).FirstOrDefault().ID);
return View();
}
in the view
#Html.DropDownList("invoice_state", (SelectList)ViewBag.States, "--Select One--")
That works fine, the option is selected... but on my edit view which is set up mostly the same is not working.
in controller:
public async Task<IActionResult> Edit(int? id)
{
var invoice = await _context.invoice
.Include(_item => _item.invoice_state).SingleOrDefaultAsync(m => m.ID == id);
if (invoice == null)
{
return NotFound();
}
string state = "start_finish"; // as a default
var states = _context.invoice_state.Select(c => new { id = c.ID, title = c.title }).ToList();
if (null != invoice.invoice_state)
{
ViewBag.State = invoice.invoice_state.alias;
}
else
{
ViewBag.State = state;
}
ViewBag.States = new SelectList(states, "id", "title", _context.invoice_state.Where(e => e.alias == state).FirstOrDefault());
return View(invoice);
}
and in the edit view
#Html.DropDownList("invoice_state", (SelectList)ViewBag.States, "--Select One--")
I have read all over the place and can't find a simple answer that isn't wire up more files, and even those haven't helped get me to the need. I have tried to force it too and it is not working, but figured it was worth placing here too.
ViewBag.States = _context
.invoice_state
.Select(c => new SelectListItem {
Value = c.ID.ToString(),
Text = c.title
})
.Select(l => new SelectListItem {
Selected = (l.Value == invoice.invoice_state.ID.ToString()),
Text = l.Text,
Value = l.Value
});
but only get 'Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable<Microsoft.AspNetCore.Mvc.Rendering.SelectListItem>' to 'Microsoft.AspNetCore.Mvc.Rendering.SelectList' or the list version of the error if i add .ToList() on the select like before.
Some people have suggested to set the selected value, and as i read it it would be like,
if (null != invoice.invoice_state)
{
ViewBag.invoice_stateID = invoice.invoice_state.ID;
}
else
{
ViewBag.invoice_stateID = _context.invoice_state.Where(e => e.alias == "start_finish").FirstOrDefault().ID;
}
if i use
<select asp-for="invoice_state" asp-items="#ViewBag.States" >
<option>Please select one</option>
</select>
It doesn't work either, see the list but nothing selected. Last note, if I select it and submit it, it does set the value in the database, just when I get back to the edit it again fails to again select anything.
Also to be clear there is the data
which came from
<dt>
#Html.DisplayNameFor(model => model.invoice_state)
</dt>
<dd>
#Html.DisplayFor(model => model.invoice_state)
</dd>
#Stephen Muecke is right, the ticket is the ViewModel. Not a fan fully here but I'll simmer. The solution is not just getting it to show, you need to save is too. Here is the whole of it.
ViewModel
namespace project_name.Models.InvoiceViewModel
{
public class EditInvoiceViewModel
{
public int invoice_stateID { get; set; }
public invoice invoice { get; set; }
public List<SelectListItem> States { set; get; }
}
}
edit in action on controller
public async Task<IActionResult> Edit(int? id)
{
var invoice = await _context.invoice
.Include(_item => _item.invoice_state).SingleOrDefaultAsync(m => m.ID == id);
string state = "start_finish"; // as a default
var states = _context.invoice_state.Select(c => new { id = c.ID, title = c.title }).ToList();
if (null != invoice.invoice_state)
{
ViewBag.State = invoice.invoice_state.alias;
}
else
{
ViewBag.State = state;
}
var vm = new EditInvoiceViewModel();
vm.invoice = invoice;
vm.States = _context
.invoice_state
.Select(c => new SelectListItem
{
Value = c.ID.ToString(),
Text = c.title
})
.ToList();
if (null != invoice.invoice_state)
{
vm.invoice_stateID = invoice.invoice_state.ID;
} else {
vm.invoice_stateID = _context.invoice_state.Where(e => e.alias == "start_finish").FirstOrDefault().ID;
}
return View(vm);
}
to save in action on controller
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Edit(EditInvoiceViewModel model)
{
if (ModelState.IsValid)
{
try
{
model.invoice.creator = await GetCurrentUserAsync();
model.invoice.invoice_state = await _context.invoice_state.SingleOrDefaultAsync(m => m.ID == model.invoice_stateID);
_context.Update(model.invoice);
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!invoiceExists(model.invoice.ID))
{
return NotFound();
}
else
{
throw;
}
}
return RedirectToAction("Index");
}
return View(model);
}
And in the view
<div class="form-group">
<label asp-for="#Model.invoice_stateID" class="col-md-2 control-label"></label>
<select asp-for="#Model.invoice_stateID" asp-items="#Model.States" >
<option>Please select one</option>
</select>
</div>
The thing I guess I was having a hard time with is all supporting questions that are like this, and all the blogs focus on the display, but i still need to save it, and that was not clear. I had to skip the [bind()] but I'll get back to that.
I'm having trouble understanding how to retrieve and edit the DevId values from my CustomerDevice table in my database to the CheckBoxList based on the CustId value.
My Index Action Method for the CustomerDeviceController displays a list of Customers from my Customers table. I have an ActionLink labeled "Edit" that passes the CustId value to the CustomerDeviceController [HttpGet] Edit(int? id) Action Method which currently displays all CheckBoxListItem values from the Devices table. However, the CheckBoxList does not display the checked DevId values from the CustomerDevice table in the database to the CheckBoxList that pertain to the CustId, instead it displays a check for each of the CheckBoxList values.
The part that I'm having trouble understanding and figuring out, is how can I display the selected DevId values from the CustomerDevice table in my database to the CheckBoxList based on the CustId and then Edit/Update the modified CheckBoxListItems on the [HttpPost] Edit Action Method back to my CustomerDevice table in my database if need be.
Please see the following code below that I have so far.
Models
public class CheckBoxListItem
{
public int ID { get; set; }
public string Display { get; set; }
public bool IsChecked { get; set; }
}
public class Customer
{
public int CustId { get; set; }
public string CustDisplayName { get; set; }
public string CustFirstName { get; set; }
....
}
public class Device
{
public int DevId { get; set; }
public string DevType { get; set; }
}
public class CustomerDevice
{
public int CustId { get; set; }
public int DevId { get; set; }
public Customer Customer { get; set; }
public Device Device { get; set; }
}
ViewModels
public class CustomerDeviceFormViewModel
{
public int CustId { get; set; }
public string CustDisplayName { get; set; }
public List<CheckBoxListItem> Devices { get; set; }
}
CustomerDeviceController
public ActionResult Edit(int? id)
{
if (id == null)
{
return NotFound();
}
var customervm = new CustomerDeviceFormViewModel();
Customer customer = db.Customers.SingleOrDefault(c => c.CustId == id);
if (customer == null)
{
return NotFound();
}
customervm.CustId = customer.CustId;
customervm.CustDisplayName = customer.CustDisplayName;
// Retrieves list of Devices for CheckBoxList
var deviceList = db.Devices.ToList();
var checkBoxListItems = new List<CheckBoxListItem>();
foreach (var device in deviceList)
{
checkBoxListItems.Add(new CheckBoxListItem()
{
ID = device.DevId,
Display = device.DevType,
IsChecked = deviceList.Where(x => x.DevId == device.DevId).Any()
});
}
customervm.Devices = checkBoxListItems;
return View(customervm);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(CustomerDeviceFormViewModel vmEdit)
{
if (ModelState.IsValid)
{
Customer customer = db.Customers.SingleOrDefault(c => c.CustId == vmEdit.CustId);
if (customer == null)
{
return NotFound();
}
foreach (var deviceId in vmEdit.Devices.Where(x => x.IsChecked).Select(x => x.ID))
{
var customerDevices = new CustomerDevice
{
CustId = vmEdit.CustId,
DevId = deviceId
};
db.Entry(customerDevices).State = EntityState.Modified;
}
db.SaveChanges();
return RedirectToAction("Index");
}
return View(vmEdit);
}
Edit.chtml
<div class="form-group">
Please select the Devices to assign to <b>#Html.DisplayFor(c => c.CustDisplayName)</b>
</div>
<div class="form-group">
#Html.EditorFor(x => x.Devices)
</div>
#Html.HiddenFor(c => c.CustId)
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
Shared/EditorTemplate/CheckBoxListItem.chtml
<div class="checkbox">
<label>
#Html.HiddenFor(x => x.ID)
#Html.CheckBoxFor(x => x.IsChecked)
#Html.LabelFor(x => x.IsChecked, Model.Display)
</label>
<br />
Your code for setting the IsChecked value will always return true (your loop is basically say if the collection contains me (which of course it does) then set it to true).
You need to get the selected values for each Customer by reading the values from your CustomerDevice table
Customer customer = db.Customers.SingleOrDefault(c => c.CustId == id);
if (customer == null)
{
return NotFound();
}
// Get all devices
var deviceList = db.Devices.ToList();
// Get the selected device ID's for the customer
IEnumerable<int> selectedDevices = db.CustomerDevices
.Where(x => x.CustId == id).Select(x => x.DevId);
// Build view model
var model = new CustomerDeviceFormViewModel()
{
CustId = customer.CustId,
CustDisplayName = customer.CustDisplayName,
Devices = deviceList.Select(x => new CheckBoxListItem()
{
ID = x.DevId,
Display = x.DevType,
IsChecked = selectedDevices.Contains(x.DevId)
}).ToList()
};
return View(model);
Here's a snippet of Razor code that I've used:
foreach (SelectListItem p in Model.PositionList)
{
#Html.Raw(p.Text + "<input type=checkbox name=\"PositionIDs\" id=\"PositionIDs\" value=" + #p.Value + (Model.Positions != null && Model.Positions.Any(pos => pos.ScoreCardId == Convert.ToInt32(p.Value)) ? " checked />" : " />"));
}
You might want to have a look at the MvcCheckBoxList NuGet package:
https://www.nuget.org/packages/MvcCheckBoxList/
This makes doing some powerful stuff with a CheckBoxList much easier in MVC - and may be a better approach to fixing your CheckBox issues.
Below is the error i getting :
The model item passed into the dictionary is of type 'System.Collections.Generic.List[StoredProcedureEF_MVC.tbl_users]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable[StoredProcedureEF_MVC.Models.User]'.
I have tried a lot but don't know where i was doing wrong, no luck from last two days. I am learning MVC, so sorry if you got some stupid mistake.
My Model :
namespace StoredProcedureEF_MVC.Models
{
[Table("tbl_users")]
public class User
{
[Key]
public int UserId { get; set; }
[Required]
public string Username {get;set;}
[Required]
public string Email { get; set; }
}
}
VIEW:
#model IEnumerable<StoredProcedureEF_MVC.Models.User>
#{
ViewBag.Title = "Delete";
}
#{
var grid = new WebGrid(source: Model);
}
#grid.GetHtml(
columns: grid.Columns(
grid.Column("UserID"),
grid.Column("Username"),
grid.Column("Email"),
grid.Column(
format: (item) => Html.ActionLink("Delete", "DeleteUser", new {id=item.UserID })
)
)
)
CONTROLLER ACTION:
[HttpGet]
public ActionResult Delete()
{
SPEFMVCEntities conn = new SPEFMVCEntities();
var result = (from p in conn.tbl_users select p).ToList();
return View(result);
}
try
var result = conn.tbl_users.Select(c => new StoredProcedureEF_MVC.Models.User
{
UserId = c.UserId,
UserName = c.UserName,
Email = c.Email
}).ToList();
return View(result);
Try to change your controller method to this:
[HttpGet]
public ActionResult Delete()
{
SPEFMVCEntities conn = new SPEFMVCEntities();
var result = (from p in conn.tbl_users select p as StoredProcedureEF_MVC.Models.User).ToList();
return View(result);
}