For some reason, when I press any of the buttons of my view, all properties of the model passed to the action method are null:
View:
#using (Html.BeginForm("FolderChange", "EdiSender", FormMethod.Post, new {id = "ediFilesForm"}))
{
var directoriesSelectList = new SelectList(Model.Directories);
#Html.DropDownListFor(m => m.SelectedDirectory, directoriesSelectList, new {#Id = "Directories", #style = "width:Auto;", #size = 20, onchange = "$('#ediFilesForm').submit()", name = "action:FolderChange"})
var ediFilesSelectList = new SelectList(Model.EdiFileNames);
#Html.DropDownListFor(m => m.SelectedEdiFile, ediFilesSelectList, new {#Id = "EdiFileNames", #style = "width:Auto;", #size = 20})
}
<br/>
...
<form action="" method="post">
<input type="submit" value="Send" name="action:Send" />
<input type="submit" value="Delete" name="action:Delete" />
<input type="submit" value="Refresh" name="action:Refresh" />
</form>
Controller:
[HttpPost]
[MultipleButton(Name = "action", Argument = "Send")]
public ActionResult Send(EdiFileModel ediFileModel)
{
....
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class MultipleButtonAttribute : ActionNameSelectorAttribute
{
public string Name { get; set; }
public string Argument { get; set; }
public override bool IsValidName(ControllerContext controllerContext, string actionName, MethodInfo methodInfo)
{
var isValidName = false;
var keyValue = string.Format("{0}:{1}", Name, Argument);
var value = controllerContext.Controller.ValueProvider.GetValue(keyValue);
if (value != null)
{
controllerContext.Controller.ControllerContext.RouteData.Values[Name] = Argument;
isValidName = true;
}
return isValidName;
}
}
It used to work when my buttons were within the Html.BeginForm() block, but I cannot have it like that anymore, because it has now action name as FolderChange(), which is different from e.g. Send() or other action method that handles button press.
Thanks.
EDITED:
#section scripts
{
<sctipt type="text/javascript">
$("#Directories").change(function () {
var selectedDirectory = $("#Directories").val();
$(function () {
$.getJSON('/DoWork/FolderChangeAjaxCall?selectedDirectory=' + selectedDirectory, function (result) {
var ddl = $('#EdiFileNames');
ddl.empty();
$(result).each(function () {
$(document.createElement('option'))
.attr('value', this.Id)
.text(this.Value)
.appendTo(ddl);
});
});
});
});
</sctipt>
}
<h2>Existing EDI Files</h2>
#using (Html.BeginForm("FolderChange", "EdiSender", FormMethod.Post, new {id = "ediFilesForm"}))
{
var directoriesSelectList = new SelectList(Model.Directories);
#Html.DropDownListFor(m => m.SelectedDirectory, directoriesSelectList, new {#Id = "Directories", #style = "width:Auto;", #size = 20})
var ediFilesSelectList = new SelectList(Model.EdiFileNames);
#Html.DropDownListFor(m => m.SelectedEdiFile, ediFilesSelectList, new {#Id = "EdiFileNames", #style = "width:Auto;", #size = 20})
Here it is, it's probably way off from what you thought the answer would be, but it will cascade the dropdowns. Your going to have to substitute your values and context in, but it will work. Now you can place your buttons in the form and not have to have the dropdown's submit the form, which is pretty poor design anyways.
#Html.DropDownListFor(x => x.ddlID, Model.myDDLList, new { id = "ddl" })
#Html.DropDownListFor(x => x.myDDLList2, Model.myDDLList2, new { id = "foo" })
Script
$("#ddl").change(function () {
var Id = $("#ddl").val(); //1st dropdown Value
$(function () {
$.getJSON('/DoWork/AjaxCall?Id=' + Id, function (result) {
var ddl = $('#foo');
ddl.empty();
$(result).each(function () {
$(document.createElement('option'))
.attr('value', this.Field1)
.text(this.Field2)
.appendTo(ddl);
});
});
});
});
Controller
public ActionResult AjaxCall(int Id)
{
using (PerformanceEntities context = new PerformanceEntities())
{
return this.Json(
(from obj in context.ACCOUNT.Where(x => x.ACCT_ID == Id).ToList()
select new
{
Field1 = obj.ACCT_ID,
Field2 = obj.ACCT_NAME
}),
JsonRequestBehavior.AllowGet
);
}
}
You can check out this post for reference
Related
I want to add a drop down menu filter for the view that contains clients and projects. My filter works on a single model view (Project), but I do not know how to apply the same to my OnGet action so that the resulting view is filtered on the sub-model (Project).
I have added the filter code to the OnGet action for the Project model, but do not know where to include the variable that will process the search filter.
The Index.cshtml.cs file (dsmIQ should be used to apply the filter when the user clicks on the Search button)
[BindProperty]
public List<ClientVM> ClientVMList { get; set; }
//added for filter - start
public string CurrentFilter { get; set; }
//added for filter - end
//added for filter - string searchString
public async Task<IActionResult> OnGet(string searchString)
{
//added for filter - start
CurrentFilter = searchString;
IQueryable<Project> dsmIQ = from s in _context.Project
select s;
if (!String.IsNullOrEmpty(searchString))
{
dsmIQ = dsmIQ.Where(s => s.DSM.Contains(searchString));
}
//added for filter - end
var clientlist = _context.Client
.Include(c => c.ClientComments)
.Include(p => p.Projects)
.ThenInclude(pc => pc.ProjectComments).ToList();
ClientVMList = new List<ClientVM>();
foreach (var item in clientlist)
{
ClientVM clientVM = new ClientVM()
{
Projectlist = new List<ProjectVM>(),
};
clientVM.ClientName = item.ClientName;
if (item.ClientComments != null && item.ClientComments.Any())
{
clientVM.ClientStatusComment = item.ClientComments.OrderByDescending(cc => cc.LastUpdateDate).First().ClientStatusComment;
clientVM.ClientRAG = item.ClientComments.OrderByDescending(cc => cc.LastUpdateDate).First().ClientRAG;
clientVM.ClientStatusCommentId = item.ClientComments.OrderByDescending(cc => cc.LastUpdateDate).First().Id;
}
else
{
clientVM.ClientStatusComment = "No Status Comment";
}
foreach (var projectItem in item.Projects)
{
ProjectVM projectVM = new ProjectVM
{
ProjectPID = projectItem.PID,
ProjectName = projectItem.ProjectName,
ProjectStatusName = projectItem.ProjectStatus,
ForecastOwnerLongName = projectItem.ForecastOwner,
DSMLongName = projectItem.DSM,
};
if (projectItem.ProjectComments != null && projectItem.ProjectComments.Any())
{
projectVM.ProjectStatusComment = projectItem.ProjectComments.OrderByDescending(pc => pc.LastUpdateDate).First().ProjectStatusComment;
projectVM.RAGStatusName = projectItem.ProjectComments.OrderByDescending(pc => pc.LastUpdateDate).First().ProjectRAG;
projectVM.ProjectStatusCommentId = projectItem.ProjectComments.OrderByDescending(pc => pc.LastUpdateDate).First().Id;
}
else
{
projectVM.ProjectStatusComment = "No Status Comment";
}
clientVM.Projectlist.Add(projectVM);
}
ClientVMList.Add(clientVM);
}
return Page();
Working code on single model (Project)
public IList<Project> Project { get;set; }
//added for filter - start
public string CurrentFilter { get; set; }
//added for filter - end
//added for filter - string searchString
public async Task OnGetAsync(string searchString)
{
//added for filter - start
CurrentFilter = searchString;
IQueryable<Project> dsmIQ = from s in _context.Project
.Include(p => p.Client)
select s;
if (!String.IsNullOrEmpty(searchString))
{
dsmIQ = dsmIQ.Where(s => s.DSM.Contains(searchString));
}
Project = await dsmIQ.AsNoTracking().ToListAsync();
//added for filter - end
// Project = await _context.Project
// .Include(p => p.Client).ToListAsync();
}
}
}
Code on Index.cshtml page:
<form asp-page="./Index" method="get">
<div class="form-actions no-color">
<p>
My projects only:
<input type="text" name="SearchString" value="#Model.CurrentFilter" />
<input type="submit" value="Search" class="btn btn-primary" /> |
<a asp-page="./CommentGroupings/Index">Back to full List</a>
</p>
</div>
</form>
My View lists all projects by Client with related comments. I want the user to be able to search for all projects where their name is held (DSM field). How can I include the IQueryable<Project> dsmIQ = from s in _context.Project in the .Include(p => p.Projects) of my var clientlist = _context.Client?
function GetStatevalue() {
var state_id= $("#ddlstate").val();
var city = $("#txtcity").val();
var datao = new Object();
datao={ state:state_id ,city_name: city }
var url = "/city/AddCity";
$.ajax({
url: url,
data:datao ,
cache: false,
type: "POST",
dataType: "json",
success: function (datao) {
},
error: function (reponse) {
alert("error : " + state_id);
}
});
Html Form
#Html.DropDownListFor(model => model.tbl_state.coutry_id, (SelectList)ViewBag.country_nm, "Select Country", new {#id="coutry_id" , #onchange="GetState(this.value)"})
<select id="ddlstate" name="ddlstate" style="width: 200px" >
#Html.TextBoxFor(model =>model.tbl_city.city_name ,new {#id="txtcity" })
<input type="submit" id="save" value="Add" name="actiong" onclick="GetStatevalue();" />
Controller
[HttpPost]
public ActionResult AddCity(int id,String city_name)
{
tbl_city data = new tbl_city();
data.city_name = city_name;
data.state_id = id;
db.tbl_city.Add(data);
db.SaveChanges();
return Json(data);
}
The parameters dictionary contains a null entry for parameter 'id' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.ActionResult AddCity(Int32, System.String)' in 'test_app.Controllers.cityController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter. Parameter name: parameters
After seeing your JqueryCode , you actionresult method should look like:
[HttpPost]
public ActionResult AddCity(int state,String city_name)
//bcoz{ state(action variablename):state_id ,city_name(action variablename): city }
{
tbl_city data = new tbl_city();
data.city_name = city_name;
data.state_id = id;
db.tbl_city.Add(data);
db.SaveChanges();
return Json(data);
}
hi i have the following Edit action to the Edit view
public ActionResult Edit(int id)
{
var deparments = db.Departments.Select(e => new DepartmentModel { DeparmentId = e.DepartmentId, Name = e.Name }).ToList();
List<SelectListItem> ddl = new List<SelectListItem>();
foreach (var item in deparments)
{
ddl.Add(new SelectListItem { Text = item.Name, Value = item.DeparmentId.ToString() });
}
var employee = db.Employees.Where(e => e.EmpId == id)
.Select(e => new NewEmployeeDeparmentDDLViewModel
{
EmpID = e.EmpId,
FirstName = e.FirstName,
LastName = e.LastName,
DeptColl = ddl,
DeptId = e.DepartmentId.ToString() //this set the selected value
});
return View(employee);
}
its Edit view:
#model VirtualCampus2.Models.NewEmployeeDeparmentDDLViewModel
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Edit</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>NewEmployeeDeparmentDDLViewModel</legend>
<div class="editor-label">
#Html.LabelFor(model => model.EmpID)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.EmpID)
#Html.ValidationMessageFor(model => model.EmpID)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FirstName)
#Html.ValidationMessageFor(model => model.FirstName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.LastName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.LastName)
#Html.ValidationMessageFor(model => model.LastName)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.DeptId)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.DeptId)
#Html.ValidationMessageFor(model => model.DeptId)
</div>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
it complains with this error show on video
error in text is:
The model item passed into the dictionary is of type
'System.Data.Entity.Infrastructure.DbQuery`1[VirtualCampus2.Models.NewEmployeeDeparmentDDLViewModel]',
but this dictionary requires a model item of type
'VirtualCampus2.Models.NewEmployeeDeparmentDDLViewModel'.
updates:
public class NewEmployeeDeparmentDDLViewModel
{
public int EmpID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<SelectListItem> DeptColl { get; set; }
public string DeptId { get; set; }
}
what it throws this error and how do i fix this?
In your Index code I made some false data (Test purposes only)
public ActionResult Index()
{
List<SelectListItem> ddlColl = new List<SelectListItem>
{
new SelectListItem{ Text="By Emp No", Value="1", Selected=true },
new SelectListItem{ Text="By Name", Value="2" }
};
List<EmployeeModel> list = new List<EmployeeModel>();
for (var i = 0; i < 10; i++)
{
var employee =
new EmployeeModel
{
EmpID = 1,
FirstName = "Name" + i.ToString(),
LastName = "LastName" + i.ToString(),
DeptId = i * 10,
DepartmentName = "DepName" + i.ToString()
};
list.Add(employee);
}
IEnumerable<EmployeeModel> employees = list;
EmployeeViewModel evm = new EmployeeViewModel { DDLCollecton = ddlColl, Employees = employees };
return View(evm);
}
In your Edit code I made some false data (Test purposes only)
public ActionResult Edit(int id)
{
List<DepartmentModel> list = new List<DepartmentModel>();
for (var i = 0; i < 10; i++)
{
var department =
new DepartmentModel
{
DeparmentId = i * 10,
Name = "DepName" + i.ToString()
};
list.Add(department);
}
IEnumerable<DepartmentModel> deparments = list;
List<SelectListItem> ddl = new List<SelectListItem>();
foreach (var item in deparments)
{
ddl.Add(new SelectListItem { Text = item.Name, Value = item.DeparmentId.ToString() });
}
List<EmployeeModel> listr = new List<EmployeeModel>();
for (var i = 0; i < 10; i++)
{
var employeer =
new EmployeeModel
{
EmpID = 1,
FirstName = "Name" + i.ToString(),
LastName = "LastName" + i.ToString(),
DeptId = i * 10,
DepartmentName = "DepName" + i.ToString()
};
listr.Add(employeer);
}
IEnumerable<EmployeeModel> employees = listr;
var Selectedemployee = employees.Where(e => e.EmpID == id)
.Select(e => new NewEmployeeDeparmentDDLViewModel
{
EmpID = e.EmpID,
FirstName = e.FirstName,
LastName = e.LastName,
DeptColl = ddl,
DeptId = e.DeptId.ToString() //this set the selected value
}).FirstOrDefault();
return View(Selectedemployee);
}
It works perfectly so your issue is with getting the DB data not the controller code itself.
Make sure that employee in the Edit controller is either a:
IEnumerable<EmployeeModel>
or
List<EmployeeModel>
Maybe something like would be good for debugging the issue:
public ActionResult Edit(int id)
{
var deparments = db.Departments.Select(e => new DepartmentModel { DeparmentId = e.DepartmentId, Name = e.Name }).ToList();
List<SelectListItem> ddl = new List<SelectListItem>();
foreach (var item in deparments)
{
ddl.Add(new SelectListItem { Text = item.Name, Value = item.DeparmentId.ToString() });
}
var employeeList = db.Employees().ToList();
var employee = employeeList.Where(e => e.EmpId == id)
.Select(e => new NewEmployeeDeparmentDDLViewModel
{
EmpID = e.EmpId,
FirstName = e.FirstName,
LastName = e.LastName,
DeptColl = ddl,
DeptId = e.DepartmentId.ToString() //this set the selected value
}).FirstOrDefault();
return View(employee);
}
You are returning the query where you state at the top of the view that you need the model to be returned, if you only want to return one item in the model then why don't you use the following:
var employee = db.Employees.Where(e => e.EmpId == id)
.Select(e => new NewEmployeeDeparmentDDLViewModel
{
EmpID = e.EmpId,
FirstName = e.FirstName,
LastName = e.LastName,
DeptColl = ddl,
DeptId = e.DepartmentId.ToString() //this set the selected value
}).FirstOrDefault();
As for other problem:
List<SelectListItem> ddl = new List<SelectListItem>();
foreach (var item in deparments)
{
ddl.Add(new SelectListItem() { Text = item.Name, Value = item.DeparmentId.ToString() });
}
You didn't have parentheses after new SelectListItem
These two bits of code should solve your problem
The error is pretty straight-forward. The model for the view is declared as:
#model VirtualCampus2.Models.NewEmployeeDeparmentDDLViewModel
But you're passing it a collection of NewEmployeeDepartmentDDLViewModels. The fact that there's probably only one instance in that collection is beside the point. This is because you're using Where, most likely so you can call Select off of it. That's fine but you still need SingleOrDefault, to pull the instance out of the collection.
var employee = db.Employees.Where(e => e.EmpId == id)
.Select(e => new NewEmployeeDeparmentDDLViewModel
{
EmpID = e.EmpId,
FirstName = e.FirstName,
LastName = e.LastName,
DeptColl = ddl,
DeptId = e.DepartmentId.ToString() //this set the selected value
}).SingleOrDefault();
However, you should also be ensuring that you actually get something back from your query. SingleOrDefault will either return the instance or null. So you should have a condition like:
if (employee == null)
{
return new HttpNotFoundResult();
}
Before returning the view.
UPDATE
when i did that it complained about "Unable to create a constant value of type 'System.Web.Mvc.SelectListItem'. Only primitive types or enumeration types are supported in this context."
That one is actually caused by passing something to a LINQ query that can't be evaluated into a static value at query time. There's nothing like that happening here in this particular bit of code, so there's somewhere else you're making a LINQ query where this is happening. One quick example I run into constantly because I always forget on first run is with Identity's GetUserId(). Say I want to get a particular object belonging to a user:
var foo = db.Foos.Where(m => m.UserId == User.Identity.GetUserId());
That will fail with the same exception. To get around it, you need to do something like:
var userId = User.Identity.GetUserId();
var foo = db.Foos.Where(m => m.UserId == userId);
Now, the LINQ query is working with a primitive type that it can easily convert into a SQL query, whereas, before, it had no idea how to write a query that included User.Identity.GetUserId(). Other common causes are using things like IsNullOrWhiteSpace (only IsNullOrEmpty is supported) or ToLowerInvariant (only ToLower is supported).
Basically whenever a LINQ query has to be converted to a SQL query because you're hitting a database, there's only a subset of framework methods you're allowed to utilize. This is because these have to be converted into an appropriate SQL equivalent, which not every method can be, especially custom methods you write on classes.
I can figure out why it's not binding. So I have a form where a ListBox is in a partial view which I reload everytime I click on a checkbox to fill the listbox.
The code of my ModelView for the form is :
<div class="row-fluid">
<div class="span3">
<label>Fonction(s):</label>
</div>
<div class="span9" id="ListeFonction">
#Html.Partial("ListerFonction", Model)
</div>
</div>
<div class="row-fluid">
<div class="span5 offset3">
<div class="fonctions_container">
#foreach (extranetClient.Models.Classes.FonctionContact fonction in ViewBag.Fonctions)
{
string coche = "";
if ((#Model.ListeFonctions).Any(c => c.IdFonction == fonction.IdFonction))
{
coche = "checked";
}
<input type="checkbox" #coche class="checkbox" value="#fonction.IdFonction" />#fonction.LibelleFonction <br />
}
</div>
</div>
</div>
So as you can see, I render a partial view just after the "Email" Textbox. The code for it is :
#Html.LabelFor(contact => contact.SelectedFonctionIds, "ListeFonctions")
#Html.ListBoxFor(contact => contact.SelectedFonctionIds, new MultiSelectList(Model.ListeFonctions, "IdFonction", "LibelleFonction"), new { disabled = "disabled")
The model associated to that view looks like that:
private List<int> _selectedFonctionIds;
public List<int> SelectedFonctionIds
{
get
{
return _selectedFonctionIds ?? new List<int>();
}
set
{
_selectedFonctionIds = value;
}
}
public List<FonctionContact> ListeFonctions = new List<FonctionContact>();
public MultiSelectList ListeFonctionsSelectList
{
get
{
return new MultiSelectList(
ListeFonctions,
"IdFonction", // dataValueField
"LibelleFonction" // dataTextField
);
}
}
public Contact() { }
public Contact( List<FonctionContact> listeFonctions, List<int> selectedFonctionIds)
{
this.ListeFonctions = listeFonctions;
this.SelectedFonctionIds = selectedFonctionIds;
}
public Contact(int idContact, string nom, string prenom, string email, string telephoneFixe, string telephonePort) {
this.IdContact = idContact;
this.Nom = nom;
this.Prenom = prenom;
this.Email = email;
this.TelephoneFixe = telephoneFixe;
this.TelephonePort = telephonePort;
}
public Contact(int idContact, string nom, string prenom, List<int> selectedFonctionIds, List<FonctionContact> listeFonctions, string email, string telephoneFixe, string telephonePort)
{
this.IdContact = idContact;
this.Nom = nom;
this.Prenom = prenom;
this.SelectedFonctionIds = selectedFonctionIds;
this.ListeFonctions = listeFonctions;
this.Email = email;
this.TelephoneFixe = telephoneFixe;
this.TelephonePort = telephonePort;
}
But the ListBox of the partial view is not binding with the model. I get well the other informations but not these in the listbox. Somebody has an idea ?
Why are you forcing the ListBox's id here:
#Html.ListBoxFor(contact => contact.SelectedFonctionIds,
new MultiSelectList(Model.ListeFonctions, "IdFonction", "LibelleFonction"),
new { disabled = "disabled", **id="idFonctions"** })
ListBoxFor helper is supposed to generate the ListBox's id for you, and the Id should be the same as the attribute it should bind with. Shouldn't it be SelectedFonctionIds?
Was the binding working before you started using the PartialView? Because from your previous question, I see that you had:
#Html.ListBoxFor(contact => contact.SelectedFonctionIds, Model.ListeFonctionsSelectList, new { disabled = "disabled" })
in your View (i.e., you didn't set the id attribute).
I need to pass values from three dropdownlists to the controller when user selects some value from any one of the dropdownlist.i tried like this but the value from only the dropdown selected is passed others are null values ,any help would be appreciated.
VIEW
##using (Html.BeginForm("GetFilterValues","Home",FormMethod.gET))
{
#Html.DropDownList("FClass", ViewBag.Market as SelectList, new { id = "Market" , onchange = "$(this).parents('form').submit();" })
}
#using (Html.BeginForm("GetFilterValues","Home",FormMethod.Get))
{
#Html.DropDownList("FClass", ViewBag.Class as SelectList, new { id = "FClass" , onchange = "$(this).parents('form').submit();" })
}
</td>
<td>
#Html.Label("Status")
</td>
<td>
#using (Html.BeginForm("GetFilterValues","Home",FormMethod.Get))
{
#Html.DropDownList("Status", ViewBag.Status as SelectList, new { id = "Status" , onchange = "$(this).parents('form').submit();" })
}
CONTROLLER
[HttpgET]
public void GetFilterValues()
{
string market = this.Request.Form.Get("Market");
string fclass = this.Request.Form.Get("FClass");
string status = this.Request.Form.Get("Status");
}
Try a single form trough a POST and pull the values by name using a FormCollection like this...
View:
#using (Html.BeginForm("GetFilterValues","Home", FormMethod.Post))
{
#Html.DropDownList("nameMarket", ViewBag.Market as SelectList, new { id = "Market" , onchange = "$(this).parents('form').submit();" })
#Html.DropDownList("nameClass", ViewBag.Class as SelectList, new { id = "FClass" , onchange = "$(this).parents('form').submit();" })
#Html.DropDownList("nameStatus", ViewBag.Status as SelectList, new { id = "Status" , onchange = "$(this).parents('form').submit();" })
}
Controller:
[HttpPost]
public void GetFilterValues(FormCollection collection) {
string market = Convert.ToString(collection["nameMarket"]);
string fclass = Convert.ToString(collection["nameClass"]);
string status = Convert.ToString(collection["nameStatus"]);
}