to display a value fetched from database in Html.Actionlink() in mvc3 - asp.net-mvc

i am making an application called AskQuestion where in on the first page i have a list of questions as links and below it is a textarea and a post button to post the question.
as i write inside the textarea and press the post button it is displayed inside the question list.
now i m fetching the posted questions from the database. and i need to display it as a link..
but Html.Actionlink does not support this
this is my Model class:
public class Question_Page
{
public virtual int Id { get; set; }
public virtual string Question_name { get; set; }
public virtual string Address { get; set; }
public virtual DateTime Created_Date { get; set; }
public virtual DateTime Modified_Date { get; set; }
public virtual int Created_By { get; set; }
public virtual int Modified_By { get; set; }
public virtual char Deleted { get; set; }
public Question_Page()
{
this.Deleted='F';
}
}
This is my view:
#model IEnumerable<Core.Model.Question_Page>
#{
ViewBag.Title = "Index";
}
<style type="text/css">
ul
{
list-style-type: none;
}
</style>
<h2>All Questions</h2>
<hr />
#using (Html.BeginForm("Index","Question",FormMethod.Post))
{
#Html.ValidationSummary(true)
<ul>
foreach (var item in Model) {
<li>#Html.ActionLink(item.Question_name, "answer", new { id=item.Id })</li>
}
</ul>
<label for="PostyourQuestion:">Post your Question:</label><br /><br />
#Html.TextArea("textID")
<br />
<input type="submit"/>
}
But with this i get an error saying "item does not exists in the current context"
i know i can use anchor tag also before this and i tried that too
<ul>
foreach (var item in Model) {
<li>#Html.DisplayFor(modelItem => item.Question_name)</li>
}
</ul>
but with it does not identify the url specified in href
please help me

I did a sample which looks like yours and I found out that you missed "#" before "foreach"
#foreach (var item in Model) {

The first one with "Html.ActionLink" should work. Problem can be in your Model. If your model returns null then item in this Model will cause error inside foreach loop, you should first check Model null state.
I think Html.ActionLink method is very useful in your case. But you should pass argument to identify your question, namely its id. Then you can use something like this:
foreach (var item in Model) {
<li>#Html.ActionLink(item.Question_name, "answer",new{id= item.id})</li>
}

Related

Dropdown list population from ViewModel

First of all, I know this question has been asked many, many times. I've read countless articles and Stack Overflow answers. I've tried to figure this problem out for four days and I think I need help if someone doesn't mind.
I have two databases. The employee database has a field called "DisplayName" -- the second database has a relationship with the first and they work together great. I'm able to call the two databases perfectly in another application.
You can see the in the picture Index Page
that I have a list of people. I want a dropdown below it that lists all display names in the database so employees can add themselves to the list. You'll see a dropdown in the image but it's not populated.
Seems simple. But geez. Part of a problem I'm having is my home controller already has a function to populate the list in the picture so I can't do another on that page. I've tried a lot of suggestions on a lot of sites. I get IEnumerable errors or display reference errors....
Here's my controller (again - it has nothing in it that helps the dropdown):
namespace SeatingChart.Controllers
{
public class HomeController : Controller
{
private ApplicationDbContext db = new ApplicationDbContext();
// GET: Employee
public ActionResult Index()
{
var lists = db.BreakModels
.Include("Employee")
.Include("TimeEntered")
.Include("TimeCleared")
.Include("DisplayName")
.Select(a => new HomeIndexViewModels
{
Employee = a.Employee,
DisplayName = a.EmployeeModels.DisplayName,
TimeEntered = a.TimeEntered,
TimeCleared = a.TimeCleared.Value,
Id = a.EmployeeModels.Id,
});
return View(lists);
}
View:
#model IEnumerable<SeatingChart.Models.HomeIndexViewModels>
#{
Layout = null;
}
#Html.Partial("_Header")
<div class="container_lists">
<div class="container_break col-md-8">
<h5 style="text-align:center">Break List</h5>
<table class="table-bordered col-lg-12">
#if (Model != null)
{
foreach (var item in Model)
{
if (item.TimeCleared == null)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.DisplayName)
</td>
<td>
 BV
</td>
<td>
 #item.TimeEntered.ToString("HH:mm")
</td>
</tr>
}
}
}
</table>
#using (Html.BeginForm())
{
<div class="row site-spaced">
<div class="col-3">
#Html.DropDownList("DisplayName", new SelectList(new List<string>() { "---Dispatcher---" }), new { #class = "required " })
</div>
</div>
<div class="col-3">
<input type="submit" value="Submit" class="site-control" />
</div>
}
</div>
</div>
ViewModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
namespace SeatingChart.Models
{
public class HomeIndexViewModels
{
//Break Model
public int BreakId { get; set; }
public int Employee { get; set; }
public DateTime TimeEntered { get; set; }
public DateTime? TimeCleared { get; set; }
//Employee Model
public int Id { get; set; }
public string DisplayName { get; set; }
public string DisplayNames { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool NotActive { get; set; }
public int Force { get; set; }
public string EmployeeList { get; set; }
}
}
I hope this is clear enough. I've tried so many different ways with so much code - the errors are different with everything I've tried.
Thanks in advance for your patience and help!
You can add to your viewmodel
public List<SelectListItem> Employees { get; set; }
Then you can populate this list with controller then in view just call it with:
#Html.DropDownListFor(m => m.Id, Model.Employees, new { #class = "form-control", required = "required" })
Update - how to populate list. Should work (but not tested code).
public List<SelectListItem> GetEmployeeForDropdown(List<HomeIndexViewModels> list)
{
List<SelectListItem> empList = new List<SelectListItem>();
try
{
if (list != null && list.Count > 0)
{
foreach (var item in list)
{
empList.Add(new SelectListItem { Text = item.DisplayName, Value = item.Id.ToString() });
}
}
else
{
empList.Add(new SelectListItem { Text = "No items", Value = string.Empty });
}
}
catch (Exception ex)
{
//handle exceptions here
}
return empList;
}
Edit: Remember to use your model in view!

View Not Returning Multiple Lists in Asp.net MVC [duplicate]

This question already has answers here:
Post an HTML Table to ADO.NET DataTable
(2 answers)
Closed 5 years ago.
i am new to web from desktop.
i have two models.
first
public class Item
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public double Price { get; set; }
public double Stock { get; set; }
public Category Category { get; set; }
public string ImagePath { get; set; }
}
and second is
public class Category
{
public int Id { get; set; }
public string Name { get; set; }
public bool isSelected { get; set; }
}
and a ViewModel for passing it to my view
public class ProductsVM
{
public IList<Item> items { get; set; }
public IList<Category> categories { get; set; }
}
and my controller action method looks like this
[HttpGet]
public ActionResult Products()
{
ViewBag.Message = "...Products...";
ProductsVM productsVm = new ProductsVM();
productsVm.items = db.Items.ToList();
productsVm.categories = db.Categories.ToList();
return View(productsVm);
}
[HttpPost]
public ActionResult Products(ProductsVM model)
{
ViewBag.Message = "...Categories...";
return View(model);
}
i have used it in my view like this
#using (Html.BeginForm())
{
<div class="row">
<div class="col-md-2">
#foreach (var it in Model.categories.ToList())
{
<div class="input-group">
#Html.CheckBoxFor(i => it.isSelected, new { Name = "ChkCategory", id = "ChkCategory"+it.Id, #class = "Categories" }) #it.Name
#Html.HiddenFor(i => it.Name)
</div>
}
</div>
#*Loading Items...*#
<div class="col-md-10">
#for (int i = 0; i < Model.items.Count() / 3; i++)
{
<div class="row">
#foreach (var item in Model.items.Skip(i * 3).Take(3))
{
<div class="col-md-4 col-sm-6 col-xs-12">
<img src="#Url.Content(item.ImagePath)" alt="#item.Description" class="thumbnail" />
</div>
}
</div>
}
</div>
</div>
<input type="submit" value="submit" />
}
#section scripts
{
<script src="~/Scripts/Products.js"></script>
}
i have tried all the ways to get my model back when i post the from to controller
i am posting the from on checkbox click event using ajax from my products.js file.
but in my controller action method it always show the ViewModel as null.
what should i do? am i doing something wrong.
Products.js
$(function () {
console.log('Inside js......');
$('.Categories').click(function (e) {
console.log(this.id, $("#" + this.id).is(":checked"));
$.ajax({
type: "POST",
url: "/Home/Products",
success: function () {
console.log("ajax successfull....");
},
error: function () {
console.log("ajax error....");
}
});
});
});
This is your ProductsVM:
public class ProductsVM
{
public IList<Item> items { get; set; }
public IList<Category> categories { get; set; }
}
This is your action method to which you are posting:
[HttpPost]
public ActionResult Products(ProductsVM model)
When you submit your form, it will take the values from your form's controls and using the names of the controls, it will post them to the Products action. In your view (form), you have a checkbox with the name chkCategory and a hidden input with the name Name. When you post your form, it will send chkCategory and its value, and the hidden item with the name Name. When it arrives on the server side, the MVC will look for an action method named Products in your controller. Then the default binder will try to look for chkCategory and Name properties to see if the action accepts them. It will not find it. Then it will try to see if it can create a ProductsVM and it cannot because ProductsVM has 2 properties: items and categories and they do not match what you are posting so it will just choose that action and pass it null.
You have many issues in your code and it is not playing nicely with the whole MVC framework. I suggest you read Understanding MVC Model Binding and try some simple examples to get a hang of it and then try what you are doing.

ASP .NET MVC4 Adding new items to view and model binding

I create a website for my wife. She's a teacher and she would like to have a possibility to create exercises for their students. The case is that she would like to create for instance the following exercise:
Exercise 1: Fill the sentence using a correct word:
My wife is 30 ............. old
I live in this city for 30 .........
I have the following model:
public class Exercise
{
[Key]
public Guid Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ExerciseType Type { get; set; }
public DifficulityLevel DifficulityLevel { get; set; }
public List<ExerciseItem> Items { get; set; }
public DateTime TimeOfCreation { get; set; }
public DateTime TimeOfModification { get; set; }
}
public class ExerciseItem
{
[Key]
public Guid Id { get; set; }
public string Content { get; set; }
public List<ExerciseItemOption> Options { get; set; }
public ExerciseItemOption CorrectSelection { get; set; }
}
I creates a View for my Exercise. I can fill in the basic properties like Name, Description, Difficulity Level and Type. Then I would like to create a button "Add exercise item". When clicked, a partial view (or something else) should be added dynamically where new ExerciseItem can be provided.
I've tried to following:
I've added a button
#Ajax.ActionLink("Add exercise item",
"AddExerciseItem",
"Exercise", new AjaxOptions() { HttpMethod="GET", InsertionMode = InsertionMode.InsertBefore, UpdateTargetId="ExerciseItems"})
and the appropriate div:
<div id="ExerciseItems"></div>
My action method looks as follows:
public ActionResult AddExerciseItem()
{
return PartialView("ExerciseItem", new ExerciseItem());
}
and the partial view:
#model ElangWeb.Models.ExerciseItem
<fieldset>
<legend>ExerciseItem</legend>
#Html.HiddenFor(model => model.Id)
<div class="editor-label">
#Html.DisplayNameFor(model => model.Content)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Content, new { style = "width:200px" })
</div>
</fieldset>
It works fine. However when I click button for creating a whole exercise, I do not have ExerciseItem collection in my model:
public ActionResult Create(Exercise exercise)
{
using (PersistanceManager pm = new PersistanceManager())
{
exercise.Id = Guid.NewGuid();
exercise.TimeOfCreation = DateTime.Now;
exercise.TimeOfModification = DateTime.Now;
pm.ExcerciseRepository.Add(exercise);
}
return RedirectToAction("Index");
}
How should I change the code in order to bind my list of added ExerciseItem objects to my model Exercise?
Check out this article about model binding. You basically need to create special names for the exercise items so that they get bound correctly.
e.g. partial:
#model ElangWeb.Models.ExerciseItem
<fieldset>
<legend>ExerciseItem</legend>
<label>content</label>
<input type="hidden" name="ExcersiseItem.Index" value="SomeUniqueValueForThisItem" />
<input type="text" name="ExcersiseItem[SomeUniqueValueForThisItem].Name" value="#Model.Content" />
</fieldset>
You can also look at my answer to this question MVC3 Non-Sequential Indices and DefaultModelBinder. Thanks Yarx for finding it, I was actually trying to find it :)

Displaying subitems on mvc 3 form?

(warning newbie)
I am using codefirst entity framework (with MVC3) and trying to display a list of steps and its associated questions. Not sure why my syntax is throwing an exception "the ObjectContext instance has been disposed and can no longer be used for operations that require a connection.":
#model IEnumerable<COPSGMIS.Models.Step>
#{
ViewBag.Title = "Questionaire";
}
<h2>Questionaire</h2>
#using (Html.BeginForm("Questionaire", "Question", FormMethod.Post, new { id = "SignupForm" }))
{
<div>
#foreach (var item in Model)
{
<fieldset class="wizard">
<legend class="wizard">#Html.DisplayFor(modelItem => item.Title)</legend>
#foreach (var question in item.Questions)
//*** item.Questions is throwing an exception ****
{
<label for="question">#Html.DisplayFor(modelItem => question.QuestionText)</label>
<input id="question" type="text" />
}
</fieldset>
}
<p>
<input id="SaveAccount" type="button" value="Save" />
</p>
</div>
}
My model:
public int StepID { get; set; }
public int ReviewID { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public int StepOrder { get; set; }
public virtual ICollection<Question> Questions { get; set; }
My controller:
var steps = from b in db.Steps
orderby b.StepOrder
select b;
return View(steps.ToList());
When item.Questions is access, EF will try to hit the database to grab the questions for that item. If the context has been disposed, it will fail. Since you'll be looping through the questions in your view, I'd suggest adding them to your initial query using "Include".
var steps = from b in db.Steps.Include(s => s.Questions)
orderby b.StepOrder
select b;
return View(steps.ToList());

How do I bind checkboxes to the List<int> property of a view model?

I've been reading the various posts on view models and check boxes, but my brain is starting to lock up and I need a little push in the right direction.
Here's my simplified view model. I have checkboxes that need to populate the lists with their values. I don't think this can happen automagically. I'm not sure how to bridge the gap between an array of string values and a List correctly. Suggestions?
public int AlertId { get; set; }
public List<int> UserChannelIds { get; set; }
public List<int> SharedChannelIds { get; set; }
public List<int> SelectedDays { get; set; }
Have your View Model like this to represent the CheckBox item
public class ChannelViewModel
{
public string Name { set;get;}
public int Id { set;get;}
public bool IsSelected { set;get;}
}
Now your main ViewModel will be like this
public class AlertViewModel
{
public int AlertId { get; set; }
public List<ChannelViewModel> UserChannelIds { get; set; }
//Other Properties also her
public AlertViewModel()
{
UserChannelIds=new List<ChannelViewModel>();
}
}
Now in your GET Action, you will fill the values of the ViewModel and sent it to the view.
public ActionResult AddAlert()
{
var vm = new ChannelViewModel();
//The below code is hardcoded for demo. you mat replace with DB data.
vm.UserChannelIds.Add(new ChannelViewModel{ Name = "Test1" , Id=1});
vm.UserChannelIds.Add(new ChannelViewModel{ Name = "Test2", Id=2 });
return View(vm);
}
Now Let's create an EditorTemplate. Go to Views/YourControllerName and Crete a Folder called "EditorTemplates" and Create a new View there with the same name as of the Property Name(ChannelViewModel.cshtml)
Add this code ro your new editor template.
#model ChannelViewModel
<p>
<b>#Model.Name</b> :
#Html.CheckBoxFor(x => x.IsSelected) <br />
#Html.HiddenFor(x=>x.Id)
</p>
Now in your Main View, Call your Editor template using the EditorFor Html Helper method.
#model AlertViewModel
<h2>AddTag</h2>
#using (Html.BeginForm())
{
<div>
#Html.LabelFor(m => m.AlertId)
#Html.TextBoxFor(m => m.AlertId)
</div>
<div>
#Html.EditorFor(m=>m.UserChannelIds)
</div>
<input type="submit" value="Submit" />
}
Now when You Post the Form, Your Model will have the UserChannelIds Collection where the Selected Checkboxes will be having a True value for the IsSelected Property.
[HttpPost]
public ActionResult AddAlert(AlertViewModel model)
{
if(ModelState.IsValid)
{
//Check for model.UserChannelIds collection and Each items
// IsSelected property value.
//Save and Redirect(PRG pattern)
}
return View(model);
}
Part of My View Model:
public List<int> UserChannelIds { get; set; }
public List<int> SharedChannelIds { get; set; }
public List<int> Weekdays { get; set; }
public MyViewModel()
{
UserChannelIds = new List<int>();
SharedChannelIds = new List<int>();
Weekdays = new List<int>();
}
I used partial views to display my reusable checkboxes (I didn't know about editor templates at this point):
#using AlertsProcessor
#using WngAlertingPortal.Code
#model List<int>
#{
var sChannels = new List<uv_SharedChannels>();
Utility.LoadSharedChannels(sChannels);
}
<p><strong>Shared Channels:</strong></p>
<ul class="channel-list">
#{
foreach (var c in sChannels)
{
string chk = (Model.Contains(c.SharedChannelId)) ? "checked=\"checked\"" : "";
<li><input type="checkbox" name="SharedChannelIds" value="#c.SharedChannelId" #chk /> #c.Description (#c.Channel)</li>
}
}
All three checkbox partial views are similar to each other. The values of the checkboxes are integers, so by lining up my view model List names with the checkbox names, the binding works.
Because I am working in int values, I don't feel like I need the extra class to represent the checkboxes. Only checked checkboxes get sent, so I don't need to verify they are checked; I just want the sent values. By initializing the List in the constructor, I should be avoiding null exceptions.
Is this better, worse or just as good as the other solution? Is the other solution (involving an extra class) best practice?
The following articles were helpful to me:
http://forums.asp.net/t/1779915.aspx/1?Checkbox+in+MVC3
http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
Binding list with view model
This site handles it very nicely
https://www.exceptionnotfound.net/simple-checkboxlist-in-asp-net-mvc/
public class AddMovieVM
{
[DisplayName("Title: ")]
public string Title { get; set; }
public List<CheckBoxListItem> Genres { get; set; }
public AddMovieVM()
{
Genres = new List<CheckBoxListItem>();
}
}
public class MembershipViewData
{
public MembershipViewData()
{
GroupedRoles = new List<GroupedRoles>();
RolesToPurchase = new List<uint>();
}
public IList<GroupedRoles> GroupedRoles { get; set; }
public IList<uint> RolesToPurchase { get; set; }
}
//view
#model VCNRS.Web.MVC.Models.MembershipViewData
#{
ViewBag.Title = "MembershipViewData";
Layout = "~/Views/Shared/_Layout.cshtml";
int i = 0;
}
#using (Html.BeginForm("Membership", "Account", FormMethod.Post, new { id = "membershipForm" }))
{
<div class="dyndata" style="clear: left;">
<table width="100%" cellpadding="0" cellspacing="0" class="table-view list-view">
foreach (var kvp2 in Model.GroupedRoles)
{
string checkBoxId = "RolesToPurchase" + kvp2.RoleType;
<tr>
<td width="240px">
<label class="checkbox-label" for="#checkBoxId">
<input type="checkbox" class="checkbox" name="RolesToPurchase[#i]"
id="#checkBoxId" value="#kvp2.RoleType" />
#kvp2.Key
</label>
</td>
</tr>
i++;
}
<tr style="background-color: #ededed; height: 15px;">
<td colspan="5" style="text-align: right; vertical-align: bottom;">
#Html.SubmitButton(Resources.MyStrings.Views_Account_Next)
</td>
</tr>
</table>
</div>
}
//Post Action
[HttpPost]
public ActionResult Membership(MembershipViewData viewData)
{
..........................
}
}

Resources