How to add ViewBag property as html class attribute properly? - asp.net

I have this line:
#Html.ActionLink("Discounts", "ListDiscounts", "Product", null, new { #class = ViewBag.Discount })
The ListDiscounts is:
public ViewResult ListDiscounts(int nrProducts = 5)
{
ViewBag.Discount = "selected";
ProductsListViewModel model = new ProductsListViewModel
{
Products = repository.Products
.Where(p => p.Discount != false)
.Take(nrProducts)
};
return View(model);
}
The View that renders the Menu (where my separate Discounts will also be)
#model IEnumerable<string>
#Html.ActionLink("Home", "List", "Product")
#foreach (var link in Model) {
#Html.RouteLink(link, new
{
controller = "Product",
action = "List",
category = link,
page = 1
},
new
{
#class = link == ViewBag.SelectedCategory ? "selected" : null,
})
}
ListDiscounts.cshtml
#model Sportsstore.WebUI.Models.ProductsListViewModel
#{
ViewBag.Title = "ListDiscounts";
}
<h2>Discounts available</h2>
#foreach (var p in Model.Products)
{
Html.RenderPartial("ProductSummary", p);
}
I'm trying to add the selected class to my 'a' element in a view but this doesn't work. The ViewBag property remains empty when I click on that Discounts link.
The View associated with ListDiscounts is not the one where that ActionLink line is from (they're separate with the one that has it being a Partial View) but from what I understand ViewBag features have some sort of a global state so this should work?
Any ideas on what is wrong here?
EDIT: Using MVC 4

I believe there is something you are not showing us that is the problem. Perhaps you only populated the ViewBag in your post method but not your get method. I created a test application that mocks your app very closely and it works fine.
Controller
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ViewResult Index()
{
ViewBag.Discount = "selected";
return View();
}
[HttpPost]
public ViewResult Index(int nrProducts = 5)
{
var model = new ProductsListViewModel{Products = "stuff"};
ViewBag.Discount = "selected";
return View(model);
}
}
}
View
#model MvcApplication1.Models.ProductsListViewModel
#Html.ActionLink("Discounts", "Index", "Home", null, new { #class = ViewBag.Discount })
#{ Html.RenderPartial("ViewPage1");}
#using (Html.BeginForm())
{
<input type="submit" />
}
Partial
#Html.ActionLink("Discounts", "Index", "Home", null, new { #class = ViewBag.Discount })
When I view the source both links have the class I expected. Also after I click on the link they have the class expected. Thus I believe you are not populating the view bag either on the Get and/or the Post controller method

If you're sure that you have value in the viewbag property instead of
#class = ViewBag.Discount try
#class = #ViewBag.Discount and see if it works

You just try the below code. Change the Viewbag name and try.
#Html.ActionLink("Discounts", "ListDiscounts", "Product", null, new { #class = ViewBag.CssDiscount })
public ViewResult ListDiscounts(int nrProducts = 5)
{
ViewBag.CssDiscount = "selected";
ProductsListViewModel model = new ProductsListViewModel
{
Products = repository.Products
.Where(p => p.Discount != false)
.Take(nrProducts)
};
return View(model);
}

Related

Getting Null value in parameter of Action method

I am getting null value in the parameter of my action method.
this is my action method
[HttpGet]
public ActionResult ProjectData(int? formId)
{
if (formId == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
return View();
}
}
and this is my view of actionlink
#foreach (var projects in Model)
{
int formId = Convert.ToInt32(#projects.FormId);
<tr>
<td>#projects.Serial</td>
<td>#projects.ProjectName</td>
#*<td>#projects.SurveyName</td>*#
#*<td>#Html.ActionLink(#projects.SurveyName, "ActionName", new { id = #projects.FormId })</td>*#
<td>#Html.ActionLink(#projects.SurveyName, "ProjectData" , "Home", new {id = formId}, null)</td>
<td>#projects.TotalSubmission</td>
<td>#projects.LastSubmissionTime</td>
<td>#projects.SubmissionToday</td>
</tr>
}
I am using list of user defined type model:
#model IEnumerable<MVC.ProjectInformation>
When I click on actionlink under the loop it should send id to the controller actionmethod but I get the parameter null always.
Specific Actionlink:
#Html.ActionLink(#projects.SurveyName, "ProjectData" , "Home", new
{id = formId}, null)
I can see the id by debugging on the View but on controller actionmethod I cannot get that id value.
The ActionLink's routeValues object properties need to match the parameters of the controller action.
Currently it is
new { id = formId }
which would not match the parameter of the ProjectData
public ActionResult ProjectData(int? formId)
Update to match
#Html.ActionLink(#projects.SurveyName, "ProjectData" , "Home", new {formId = formId}, null)

ERROR: Unable to cast object of type 'System.Collections.Generic.List' to type 'X.PagedList.IPagedList'

I use List instead of IEnumerable model
My Controller
public ActionResult Index(int? page)
{
var pageNumber = page ?? 1;
var itemCount = employees.ToPagedList(pageNumber, 5);
return View(employees.ToList());
}
My View
#Html.Partial("EmployeeList", Model.AsEnumerable())
#Html.PagedListPager((IPagedList)Model.AsEnumerable(), page => Url.Action("Index", new { page }))
IEnumerable<EmployeeViewModel> can't be directly cast to IPagedList with (IPagedList)Model.AsEnumerable() since they're different instances. You should return a PagedList instance using ToPagedList method as View argument (assumed employees is an List<EmployeeViewModel> or array of viewmodels):
public ActionResult Index(int? page)
{
var pageNumber = page ?? 1;
return View(employees.ToPagedList(pageNumber, 5));
}
And use the bound model inside PagedListPager like this:
#model PagedList.IPagedList<EmployeeViewModel>
#using PagedList.Mvc;
#Html.PagedListPager(Model, page => Url.Action("Index", new { page }))
And pass the IPagedList through Model in HtmlHelper.Partial:
#Html.Partial("EmployeeList", Model)
Similar issue:
How to load first x items and give user the option to load more in MVC.NET
**Controller Action **
public ActionResult Index(int? page)
{
var pageNumber = page ?? 1;
return View(employees.ToList().ToPagedList(pageNumber, 5));
}
View page
#using PagedList
#using PagedList.Mvc
#model IEnumerable <Employee>
#Html.Partial("EmployeeList", Model)
#Html.PagedListPager((IPagedList)Model, page => Url.Action("Index", new { page }))

PagedList MVC Html Helper, add key/value pairs to Html Helper

Parent View:
var pagingModel = new Watchlist_Web.Models.ViewModel.PagingPartialViewModel();
pagingModel.PagedList = Model;
pagingModel.UrlAction = "AdminIndex";
Dictionary<string, object> parameters = new Dictionary<string, object>();
parameters.Add("query", Request.QueryString["query"]);
parameters.Add("modelClass", Request.QueryString["nodeClassId"]);
pagingModel.RouteValues = new RouteValueDictionary(parameters);
pagingModel.ContainerDivClasses = "pagination-sm col-md-5";
#Html.Partial("_PagingPartial", pagingModel)
Partial View:
#using PagedList;
#using PagedList.Mvc;
#model Watchlist_Web.Models.ViewModel.PagingPartialViewModel
#Html.PagedListPager(Model.PagedList, page => Url.Action(Model.UrlAction,
new RouteValueDictionary(new { page = page })),
new PagedListRenderOptions()
{
DisplayPageCountAndCurrentLocation = true,
DisplayLinkToFirstPage = PagedListDisplayMode.IfNeeded,
DisplayLinkToLastPage = PagedListDisplayMode.IfNeeded,
ContainerDivClasses = new[] { Model.ContainerDivClasses }
})
I am attempting to add Model.RouteValues to the partial view's HTML Helper for PagedListPager. The second parameter for URL.Action is where I need to specify my route values, and having only "page" works great. However, I am trying to find a way to add the key/value pairs of Model.RouteValues to this parameter.
Implemented a utilities Class and Method that adds "page" to a new dictionary.
Utility Method:
public static RouteValueDictionary GetPagingRouteValDictionary(int page, RouteValueDictionary dict)
{
if (dict["page"] != null)
{
dict.Remove("page");
}
var newDict = new RouteValueDictionary(dict);
newDict.Add("page", page);
return newDict;
}
Partial View:
#Html.PagedListPager(Model.PagedList, page => Url.Action(Model.UrlAction,
Watchlist_Web.Utility.RouteValueDictUtil.GetPagingRouteValDictionary(page, Model.RouteValues)),
new PagedListRenderOptions()
{
DisplayPageCountAndCurrentLocation = true,
DisplayLinkToFirstPage = PagedListDisplayMode.IfNeeded,
DisplayLinkToLastPage = PagedListDisplayMode.IfNeeded,
ContainerDivClasses = new[] { Model.ContainerDivClasses }
})

ASP.NET MVC4 + Get drop down value after HttpPost submit

So I want to get a value of the dropdown (== id of the account) to insert a new transaction
Here below you can find my View:
<div id="content">
<h2>Overschrijving</h2>
<p id="topmsg">velden met een * zijn verplicht</p><p> </p>
<dl class="clearfix form">
#using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
#Html.ValidationSummary(true, "Gelieve alles correct in te vullen.")
<dt>#Html.Label("Rekening: *")</dt>
<dd>#Html.DropDownList("ddlAccounts")</dd>
<dt>#Html.Label("Begunstigde: *")</dt>
<dd>#Html.TextBox("ToAccountNumber")</dd>
<dt>#Html.Label("Bedrag: *")</dt>
<dd>#Html.TextBox("Amount", null, new { #class = "inpshort" })</dd>
<dt>#Html.Label("Mededeling: ")</dt>
<dd>#Html.TextBox("Message", null, new { #class = "inplong" })</dd>
<dd class="buttons">
<input type="submit" value="Bevestigen" />
<input type="submit" value="Annuleren" />
</dd>
}
</dl>
</div>
this is the Controller code:
public ActionResult Transfer(int? id) {
Holder h = Holder.GetHolderByHolderId(Convert.ToInt32(User.Identity.Name));
List<Account> holderAccounts = Account.GetAccountsByHolderId(h.Id);
List<SelectListItem> ddlHolderAccounts = new List<SelectListItem>();
ddlHolderAccounts.Add(new SelectListItem { Text = "selecteer...", Value = "-1", Selected = true });
foreach (Account acc in holderAccounts) {
if (acc.Id == id) {
ddlHolderAccounts.Add(new SelectListItem { Text = acc.Name, Value = acc.Id.ToString(), Selected = true });
} else {
ddlHolderAccounts.Add(new SelectListItem { Text = acc.Name, Value = acc.Id.ToString() });
}
}
ViewData["ddlAccounts"] = ddlHolderAccounts;
return View();
}
[HttpPost]
public ActionResult Transfer(Transaction tra) {
if (ModelState.IsValid) {
Transaction.InsertTransaction(tra.Amount, tra.Message, tra.FromAccountId, tra.ToAccountNumber);
}
return View(tra);
}
Now I searched a lot with Google, it's probably better to use the DropDownListFor to fill your drop down list? But could anyone show me an example?
By looking at your code, I can see that you're not passing a list of SelectListItems to the DropDownList helper. You can do this one of two ways.
1- Bind it to a property on your model:
#Html.DropDownListFor(x=>Model.Property, new List<SelectListItem> { new SelectListItem { Text = "Item1", Value = "Value1" })
Or
2- You can do it without binding to a model property like:
#Html.DropDownList("propertyName", new List<SelectListItem> { new SelectListItem { Text = "Item1", Value = "Value1" } })
If you're using the second approach then your controller action must accept "propertyName" as a parameter when submitting.
And don't forget to provide a list of SelectListItems to select from (which you're not doing in your code).
Hope this helps.
should be
#Html.DropDownListFor(x=>Model.Property, new List { new SelectListItem { Text = "Item1", Value = "Value1" }})

C# MVC3 DropDownList - No ID found in the form post

I just made a form containing a DropDownList, it perfectly shows the option names, but doesn't post the ID of the selected option into the controller.
Here is the code for the controller:
[HttpGet]
public ActionResult Insert(int id)
{
TemplateRepository repo = new TemplateRepository();
List<Template> templateList = repo.ListAll().ToList<Template>();
ViewData["Template"] = new SelectList(templateList, "Id", "Omschrijving");
return View();
}
[HttpPost]
public ActionResult InsertOrEditSubmit(Klant klant)
{
KlantRepository repo = new KlantRepository();
klant.Naam = Request["Naam"];
klant.Adres = Request["Adres"];
klant.Postcode = Request["Postcode"];
klant.Woonplaats = Request["Woonplaats"];
klant.Email = Request["Email"];
klant.Telefoon = Request["Telefoon"];
repo.SaveOrUpdate(klant);
return RedirectToAction("Index");
}
And here is the code in the view:
#using (Html.BeginForm("InsertOrEditSubmit", "Klant", FormMethod.Post))
{
#Html.DevExpress().Label(
settings =>
{
settings.ControlStyle.CssClass = "label";
settings.Text = "Template";
settings.AssociatedControlName = "Template";
}
).GetHtml() <br />
#Html.DropDownList("Template", ViewData["Template"] as SelectList);
#Html.DevExpress().Button(
settings =>
{
settings.ControlStyle.CssClass = "button";
settings.Name = "Insert";
settings.Text = "Toevoegen";
settings.UseSubmitBehavior = true;
}
).GetHtml()
#Html.DevExpress().Button(
settings =>
{
settings.ControlStyle.CssClass = "button";
settings.Name = "Cancel";
settings.Text = "Terug";
settings.ClientSideEvents.Click = "function(s, e){ document.location='" + DevExpressHelper.GetUrl(new { Controller = "Gebruiker", Action = "Index" }) + "'; }";
}
).GetHtml()
}
Hope someone can explain why it doesn't post the ID..
Try: Request["Template"];
Try a simple test:
(Controller)
ViewData["Test"] = new SelectList(new[] {new {Id = 1, Text = "Test 1"}, new {Id = 2, Text = "Test 2"}, new {Id = 3, Text = "Test 3"}}, "Id", "Text");
(View)
#Html.DropDownList("Test", ViewData["Test"] as SelectList)
Now the Request["Test"] should return the Id of the selected value.
But if your View is strongly-typed, in your case to the object "Klant", you don't need to fill the values with the Request, the object will be auto-populated and if your object have a property Template it'll be populated too.
I have found that sometimes having a name along with the id for an input solves this issue.
What does your rendered html for the Template control look like?

Resources