Context Disposed Error before DropDownListFor() get populated - linq

I have been trying to get a DropDownList to work:
My controller code is as follows:
public ActionResult Register()
{
var teams = new List<Team>();
using (var context = new TouristContext())
{
teams = (from x in context.Teams select x).ToList();
}
var model = new RegisterViewModel()
{
Teams = new SelectList(teams, "Value", "Text")
};
return View(model);
}
My DropDownListFor() code is as follows:
<div class="form-group">
#Html.LabelFor(m => m.Teams, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.DropDownListFor(m => m.SelectedTeamId, Model.Teams, "Value", "Text")
</div>
</div>
When I try and access the page I get the error:
The operation cannot be completed because the DbContext has been disposed.
I understand the error, but I have no idea how to overcome it.

It turns out the reason it was failing was because I had nothing called Value and Text!
My properties were Id and Name, so I changed my code to:
public ActionResult Register()
{
var teams = new List<Team>();
using (var context = new TouristContext())
{
teams = (from x in context.Teams select x).ToList();
}
var model = new RegisterViewModel()
{
Teams = new SelectList(teams, "Id", "Name")
};
return View(model);
}
And now all works fine.

Related

How to get selected Drop down list value in view part of MVC?

I want to pass selected Drop down list value to Ajax Action Link which is I am using in Controller. Every time When I will change drop down list value. I want that respective value pass to the action link.
What I need to write here in Ajax Action Link ????
Drop Down List
<div class="form-group">
#Html.DropDownListFor(model => model.ComponentId, ((List<string>)ViewBag.Cdll).Select(model => new SelectListItem { Text = model, Value = model }), " -----Select Id----- ", new { onchange = "Action(this.value);", #class = "form-control" })
</div>
Ajax Action Link
<div data-toggle="collapse">
#Ajax.ActionLink("Accessory List", "_AccessoryList", new { ComponentId = ???? }, new AjaxOptions()
{
HttpMethod = "GET",
UpdateTargetId = "divacc",
InsertionMode = InsertionMode.Replace
})
</div>
Controller
public PartialViewResult _AccessoryList(string ComponentId)
{
List<ComponentModule> li = new List<ComponentModule>();
// Code
return PartialView("_AccessoryList", li);
}
Here is a new post. I do dropdowns a little different than you, so I am showing you how I do it. When you ask what to pass, I am showing you how to pass the dropdown for 'component' being passed. I also show how to pass from ajax back to the page.
Controller/Model:
//You can put this in a model folder
public class ViewModel
{
public ViewModel()
{
ComponentList = new List<SelectListItem>();
SelectListItem sli = new SelectListItem { Text = "component1", Value = "1" };
SelectListItem sli2 = new SelectListItem { Text = "component2", Value = "2" };
ComponentList.Add(sli);
ComponentList.Add(sli2);
}
public List<SelectListItem> ComponentList { get; set; }
public int ComponentId { get; set; }
}
public class PassDDLView
{
public string ddlValue { get; set; }
}
public class HomeController : Controller
{
[HttpPost]
public ActionResult PostDDL(PassDDLView passDDLView)
{
//put a breakpoint here to see the ddl value in passDDLView
ViewModel vm = new ViewModel();
return Json(new
{
Component = "AComponent"
}
, #"application/json");
}
public ActionResult IndexValid8()
{
ViewModel vm = new ViewModel();
return View(vm);
}
View:
#model Testy20161006.Controllers.ViewModel
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>IndexValid8</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
$(function () {
$("#btnClick").click(function () {
var PassDDLView = { ddlValue: $("#passThis").val() };
$.ajax({
url: '#Url.Action("PostDDL")',
type: 'POST',
data: PassDDLView,
success: function (result) {
alert(result.Component);
},
error: function (result) {
alert('Error');
}
});
})
})
</script>
</head>
<body>
<div class="form-group">
#Html.DropDownListFor(m => m.ComponentId,
new SelectList(Model.ComponentList, "Value", "Text"), new { id = "passThis" })
<input type="button" id="btnClick" value="submitToAjax" />
</div>
</body>
</html>

ActionLink to submit Model value

I want my Ajax.ActionLink to pass a viewModel property to action.
Here is my ViewModel
public class ViewModel
{
public string Searchtext { get; set; }
}
My .cshtml
#Ajax.ActionLink("Bottom3", "Bottom3",new { name = Model.Searchtext}, new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "pointsDiv"
})
using(Html.BeginForm("Bottom3", "Home", FormMethod.Get))
{
#Html.TextBoxFor(x => x.Searchtext)
<button type="submit">Search</button>
}
<div id="pointsDiv"></div>
}
My Controller action:
public PartialViewResult Bottom3(string name)
{
var model = db.XLBDataPoints.OrderBy(x => x.DataPointID).Take(3).ToList();
return PartialView("Partial1", model);
}
But the name parameter passed to the action is always null. How do I solve this?
In your code... you have 2 different ways of posting to the server: the link and the form button.
The problem is that the ActionLink has no way to get the value from the input in client side... just the original value.
If you press the Search button, you will see a value posted.
Now, you can use some jQuery to modify a standard ActionLink (not the Ajax.ActionLink):
https://stackoverflow.com/a/1148468/7720
Or... you can transform your Form in order to do a Ajax post instead of a normal one:
https://stackoverflow.com/a/9051612/7720
I did this for a model of mine like so. I ONLY supported the HttpPost method. So add the HttpMethod="POST" to your Ajax.ActionLink
[HttpPost]
public ActionResult Accounts(ParametricAccountsModel model)
{
if (model.Accounts == null)
{
GetAccountsForModel(model);
}
if (model.AccountIds == null)
{
model.AccountIds = new List<int>();
}
return View(model);
}
On the razor view
#Ajax.ActionLink(
"Add Account to Order", "Accounts", "Parametric", null,
new AjaxOptions() { InsertionMode = InsertionMode.Replace, UpdateTargetId = "...", HttpMethod = "POST" },
new { #id = "AddParametricAccountLink" })
The model has a list of selected account ids. So in javascript, I modified the href of the action link dynamically.
function UpdateParametricAccountAction() {
var originalLink = '/TradeNCashMgmt/Parametric/Accounts';
var append = '';
var numberOfRows = $('#ParametricAccounts').find('.parametric-account- row').size();
for (var i = 0; i < numberOfRows; i++) {
if (i != 0) {
append += '&';
}
else {
append = '?';
}
var idValue = $('#NotionalTransactionsAccountId_' + i).val();
append += 'AccountIds%5B' + i + '%5D=' + idValue;
}
$('#AddParametricAccountLink').attr('href', originalLink + append);
}
Since the model binder looks for parameter names in the query string and form submission, it will pick up values using the href. So I posted a model object using the querystring on my Ajax.ActionLink. Not the cleanest method, but it works.

How can I access the values of my view's dropdown list in my controller?

How can I access the values of my view's dropdown list in my controller?
var typeList = from e in db.Rubrics where e.DepartmentID == 2 select e;
var selectedRubrics = typeList.Select(r => r.Category);
IList <String> rubricsList = selectedRubrics.ToList();
IList<SelectListItem> iliSLI = new List<SelectListItem>();
SelectListItem selectedrubrics = new SelectListItem();
selectedrubrics.Text = "Choose a category";
selectedrubrics.Value = "1";
selectedrubrics.Selected = true;
iliSLI.Add(selectedrubrics);
for(int i = 0;i<rubricsList.Count();++i)
{
iliSLI.Add(new SelectListItem() {
Text = rubricsList[i], Value = i.ToString(), Selected = false });
}
ViewData["categories"] = iliSLI;
In my view this works fine showing the dropdown values:
#Html.DropDownList("categories")
Then in my controller I am using FormCollection like this:
String[] AllGradeCategories = frmcol["categories"].Split(',');
When I put a breakpoint here, I get an array of 1’s in AllGradeCategories. What am I doing wrong?
MORE:
Here’s my begin form:
#using (Html.BeginForm("History", "Attendance",
new {courseID = HttpContext.Current.Session ["sCourseID"] },
FormMethod.Post, new { #id = "formName", #name = "formName" }))
{
<td>
#Html.TextBoxFor(modelItem => item.HomeworkGrade, new { Value = "7" })
#Html.ValidationMessageFor(modelItem => item.HomeworkGrade)
</td>
<td>
#Html.TextBoxFor(modelItem => item.attendanceCode, new { Value = "1" })
#Html.ValidationMessageFor(model => model.Enrollments.FirstOrDefault().attendanceCode)
</td>
<td>
#Html.EditorFor(modelItem => item.classDays)
</td>
<td>
#Html.DropDownList("categories")
</td>
}
My controller signature:
public ActionResult ClassAttendance(InstructorIndexData viewModel, int id, FormCollection frmcol, int rows, String sTeacher, DateTime? date = null)
EDITED 2
Tried this but although it seems to get posted, the I still don’t get the values of the list in the hidden field or the categories parameter.
#Html.Hidden("dropdownselected1");
#Html.DropDownList("categories",ViewBag.categories as SelectList, new { onchange = "changed" })
</td>
$(function () {
$("#dropdownselected1").val($("#categories").val());
});
If you are looking to access the selected value from the dropdown list, use a hidden field and repopulate that field on onChange() javascript event of the dropdown list.
but you can use normal
#Html.Hidden("dropdownselected1");
#Html.DropDownList("categories",new { onchange ="changed();"}
function changed()
{
$("#hiddenfieldid").val($("#dropdownlistid").val());
}
should do.
I ended up creating a ViewModel to handle just the drowdown list with an associated partial view. Then in the controller I accessed the values of the list using FormCollection().

Auto complete is not working in my asp.net MVC

i have the following repository method to search for users containing a search parameter:-
public IEnumerable<User> searchusers2(string q)
{
return from u in entities1.Users
where (u.UserID.Contains(q) || string.IsNullOrEmpty(q))
select u;
}
which is called suing the following action method:-
public ActionResult QuickSearch(string term)
{
var users = r.searchusers2(term);
users.Select(a => new { value = a.UserID });
return Json(users, JsonRequestBehavior.AllowGet);
}
and on the view i have the following code:-
#using (Ajax.BeginForm("Search", "User", new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace,
UpdateTargetId = "searchResults",
LoadingElementId = "progress"
}))
{
<input type="text" name="q" data-autocomplete-source="#Url.Action("QuickSearch", "User")" />
<input type="hidden" name="classid" value="#ViewBag.classid"/>
<input type="submit" value="Search" />
}
the above code is not working but if i change my action method to be as follow (without using a repository to perform the search) then the auto complete will work fine,,, so what might be causing this problem:-
public ActionResult QuickSearch(string term)
{
var users = entities1.Users
.Where(e => e.UserID.Contains(term))
.Select(r => new {value = r.UserID });
return Json(users, JsonRequestBehavior.AllowGet);
}
In the repository-version you're returning the whole User object in Json, The Select in
public ActionResult QuickSearch(string term)
{
var users = r.searchusers2(term);
users.Select(a => new { value = a.UserID });
return Json(users, JsonRequestBehavior.AllowGet);
}
is doing nothing because you're not storing the returned values, you'll either need to chain the call together, e.g:
public ActionResult QuickSearch(string term)
{
var users = r.searchusers2(term).Select(a => new { value = a.UserID });
return Json(users, JsonRequestBehavior.AllowGet);
}
or use a separate variable:
public ActionResult QuickSearch(string term)
{
var users = r.searchusers2(term);
var values = users.Select(a => new { value = a.UserID });
return Json(values, JsonRequestBehavior.AllowGet);
}

How do I process drop down list change event asynchronously?

I have a drop down list that I need to react to asynchronously. I cannot get the Ajax.BeginForm to actually do an asynchronous postback, it only does a full postback.
using (Ajax.BeginForm("EditStatus", new AjaxOptions { UpdateTargetId = "divSuccess"}))
{%>
<%=Html.DropDownList(
"ddlStatus",
Model.PartStatusList.OrderBy(wc => wc.SortOrder).Select(
wc => new SelectListItem
{
Text = wc.StatusDescription,
Value = wc.PartStatusId.ToString(),
Selected = wc.PartStatusId == Model.PartStatusId
}),
new { #class = "input-box", onchange = "this.form.submit();" }
)%>
<div id='divSuccess'></div>
<%
}
When the user selects an item from the list, it does a full postback and the controller method's return value is the only output on the screen. I am expecting the controller method's return value to be displayed in "divSuccess".
[AjaxAwareAuthorize(Roles = "Supplier_Administrator, Supplier_User")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditStatus(PartPropertiesViewModel partPropertiesViewModel)
{
var part = _repository.GetPart(partPropertiesViewModel.PartId);
part.PartStatusId = Convert.ToInt32(Request.Form["ddlStatus"]);
_repository.SavePart(part);
return Content("Successfully Updated Status.");
}
How about doing this the proper way using jQuery unobtrusively and getting rid of those Ajax.* helpers?
The first step is to use real view models and avoid the tag soup in your views. Views should not order data or whatever. It's not their responsibility. Views are there to display data that is being sent to them under the form of a view model from the controller. When I see this OrderBy in your view it's just making me sick. So define a clean view model and do the ordering in your controller so that in your view you simply have:
<% using (Html.BeginForm("EditStatus", "SomeControllerName", FormMethod.Post, new { id = "myForm" }) { %>
<%= Html.DropDownListFor(
x => x.Status,
Model.OrderedStatuses,
new {
#class = "input-box",
id = "myDDL"
}
) %>
<% } %>
<div id="divSuccess"></div>
and finally in a completely separate javascript file subscribe for the change event od this DDL and update the div:
$(function() {
$('#myDDL').change(function() {
var url = $('#myForm').attr('action');
var status = $(this).val();
$.post(url, { ddlStatus: status }, function(result) {
$('#divSuccess').html(result);
});
});
});
This assumes that in your controller action you would read the current status like this:
[AjaxAwareAuthorize(Roles = "Supplier_Administrator, Supplier_User")]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditStatus(PartPropertiesViewModel partPropertiesViewModel, string ddlStatus)
{
var part = _repository.GetPart(partPropertiesViewModel.PartId);
part.PartStatusId = Convert.ToInt32(ddlStatus);
_repository.SavePart(part);
return Content("Successfully Updated Status.");
}
And when you see this you might ask yourself whether you really need a form in this case and what's its purpose where you could simply have a dropdownlist:
<%= Html.DropDownListFor(
x => x.Status,
Model.OrderedStatuses,
new Dictionary<string, object> {
{ "class", "input-box" },
{ "data-url", Url.Action("EditStatus", "SomeControllerName") },
{ "id", "myDDL" }
}
) %>
<div id="divSuccess"></div>
and then simply:
$(function() {
$('#myDDL').change(function() {
var url = $(this).data('url');
var status = $(this).val();
$.post(url, { ddlStatus: status }, function(result) {
$('#divSuccess').html(result);
});
});
});

Resources