Dynamic database driven accordion in mvc - asp.net-mvc

I am using ASP.NET mvc4 with razor,i am trying to create accordion control dynamically by reading the values from the database. Could someone please point me to the example code on how to start.

based on the sample of accordion here
here what you can do in your controller
public ActionResult Index()
{
using(var db=new YourDataContext())
{
List<YourTableModel> details=db.YourTable.ToList();
return View(details)
}
}
and in your view assuming that the table you have contains Title and Description data
#model IEnumerable<YourTableModel>
<dl class="accordion">
#foreach(var detail in Model)
{
<dt>#detail.Title</dt>
<dd>#detail.Description</dd>
}
</dl>

Related

ASP.NET MVC Database Driven Menu in shared view

I need some guidance on inserting a menu in the _layout.cshtml file. I have hit two problems:
1) Even when I create an additional model to include two data models, I am unable to pass both the models to the layout file
eg:
Model:
public class IndexModel
{
public tblMenu tblMenu { get; set; }
public tblSite tblSite { get; set; }
}
I need info from the Menu table and the site table on the same page.
2) When I create a partial view to pass the menu data I continually get exceptions telling me that I can't use the model in this way.
My Partialview:
#model mvcSPS.Models.IndexModel
<li>#Model.tblMenu.MenuName</li>
My Controller:
public ActionResult _menu()
{
return PartialView(db.IndexModels.ToList());
}
My _layout.cshtml
<ul id="navigation">
#foreach (var item in Model)
{
#Html.Partial("_menu")
}
</ul>
I have trawled the net and to be quite frank.. I am having a really difficult transition from ASP classic (yes I know) to ASP.net and MVC.
Your gentle guidance would be much appreciated.
Thanks
Andrew
change your #Html.Partial in your _layout.cshtml to call the controller function and render the result of the Action method.
#foreach (var item in Model)
{
Html.RenderAction("_menu", "Home");
}
note: you shouldn't need a prepending '#' since it's in the context of the foreach loop
EDIT: Based on my comment suggestion below
HomeController:
public ActionResult Menu() {
return PartialView("_menu", db.IndexModels.ToList());
}
_layout.cshtml
#{Html.RenderAction("Menu", "Home");} //be sure to fully-qualify the controller since it's layout, otherwise it'll look to the current controller based on route values collection
_menu.cstml
<nav>
<ul>
#foreach(var item in Model) {
Html.Partial("_menuItem", item)
}
</ul>
</nav>
_menuItem.cshtml
#foreach(var item in Model) {
<li>
text
#if(item.Children.Any())
{
<ul>
Html.Partial("_menuItem", item.Children)
</ul>
}
</li>
}

Viewing controller data in VIEW

i'm newbie to MVC 3.0 and LINQ to SQL. called store procedure and saved it result in VAR but now how to view it's data in VIEW ?
CODE:
using EmployeeAttendance_app.Models;
namespace EmployeeAttendance_app.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Employee Attendance";
var DataContext = new EmployeeAtdDataContext();
var EmployeeAtd = DataContext.GetAttendance_Sp;
return View(EmployeeAtd);
}
public ActionResult About()
{
return View();
}
}
}
SP:
Select * from V_EmpAtd
View:
#foreach (GetAttendance_SpResult emp in (IEnumerable<Object>)ViewData.Model)
{
<li>#emp.DeptName</li>
}
this view shows the results, successfully :) but i don't understand that why do i need "GetAttendance_SpResult" in foreach and how
return View(EmployeeAtd);
in controller is related to this ?
right click within your action and select 'Create View'
public ActionResult Index()
{ // right click here...
then visit the view /HomeController
Where is your model? "M" "V" "C" ;-)
First you should create a class (your model, called for example EmployeeModel- you should take a name corresponding to the type of your data) corresponding to the fields of your items of your database results. How? Look here:
http://www.asp.net/mvc/tutorials/mvc-5/introduction/adding-a-model
The list of items corresponding to that model will be passed to your View in your controller so your view should start with:
#model IEnumerable<yourNameSpace.Models.EmployeeModel>
And then in your view you will be able to display the properties of your item. Sample for a table:
<table>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.DeptName)
</td>
</tr>
}
</table>
But you can do what you want: a list, ...
In a few words: back to MVC basics. See sample here: http://www.asp.net/mvc/tutorials/mvc-5/introduction/accessing-your-models-data-from-a-controller, especially when they are in "Examining the Generated Code".

ViewBag.Title vs. Page.Title in ASP.NET MVC 3

Why sometimes #ViewBag.Title contains the right page title while #Page.Title is null? We are debugging our View/Layout code and we noticed this difference.
Thanks.
When your are using asp.Net MVC you have a few tools you can use to get data to your page.
The model you send to the view.
The ViewBag.
TempData.
Cookies.
Session.
Each one of theese has their own use cases
The example we will be using is a basic
List and update View
For a collection of companies
The Model
The model Should be used whenever you have a defined dataset being sent to a view and should contain the primary data for the page and usally a model is specific to a page or controller.
The ViewBag
The ViewBag should be used whenever you need to send general data to a page that is not defined on the model or data that is used across your view tree.
Temp Data
Temp Data is as the name states storage for temporary data this should be used in cases where you are unsure if the data will reach its destination or when you want to pass data between actions without adding parameters.
Cookies
Cookies are like Global variables the host data across your entire application.
Session
Sessions like cookies are global variables but differ in their lifetime sessions can be used for things like Storing form data between requests dont use session to do this rather use something like http://garlicjs.org/
Lets look at the example
We have the following ViewModel
public class Company
{
public int? id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
The layout page looks like this
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
//This looks for the Title property on the ViewBag and inserts it in the title tags
<title>#ViewBag.Title</title>
</head>
<body>
#Html.Action("Header", "PageElements")
#RenderBody()
</body>
</html>
The Header Action on the PageElements Contoller looks like this
public PartialViewResult Header()
{
ViewBag.CurrentLink = HttpContext.Current.Request.Cookies["CurrentLink"];
return PartialView();
}
The Header Partial View looks like this
<header>
<ul>
<li class="#(ViewBag.CurrentLink == "Home" ? "Current" : "")">
#Html.ActionLink("Home", "Index", "Home")
</li>
<li class="#(ViewBag.CurrentLink == "Companies" ? "Current" : "")">
#Html.ActionLink("Companies", "Index", "Companies")
</li>
</ul>
</header>
The controller action for update looks like this
public ViewResult Update(int id)
{
//Gets a company from the database
var model = db.GetCompany(id);
//Sets The Title property on the ViewBag to Update : CompanyName
ViewBag.Title = String.Format("Update : {0}", model.Name);
//Sends the company to the view
return View(model);
}
The update view looks like this
#model Application.Models.Company
#{
Layout = "_layout.cshtml";
}
#using (Html.BeginForm())
{
#Html.HiddenFor(model => Model.id)
#Html.LabelFor(model => Model.Name)
#Html.TextBoxFor(model => Model.Name)
#Html.LabelFor(model => Model.Description)
#Html.TextAreaFor(model => Model.Description)
<button>Submit</button>
}
The Post Action for Update looks like this
[HttpPost]
public ActionResult Update(Company model)
{
//Attempts to update the model
if (model.Update())
{
//Set the message to update succeeded
TempData["Message"] = String.Format("{0} Successfully updated");
}
else
{
//Set the message to update failed
TempData["Message"] = String.Format("{0} filed to update");
}
return RedirectToAction("Index");
}
The Controller action for companies looks like this
public ViewResult Index()
{
//Index is the entrypoint for companies so we set the currentlink to companies while we are in companies
HttpContext.Current.Request.Cookies["CurrentLink"] = "Companies";
//Gets the success or failure message from the temp data
ViewBag.Message = TempData["Message"];
//Sets The Title property on the ViewBag to List of companies
ViewBag.Title = "List of companies";
var model = db.GetAllCompanies();
return View(model);
}
The view for the list looks like this
#model IEnumrable<Application.Models.Company>
#{
Layout = "_layout.cshtml";
}
<span>#ViewBag.Message</span>
<ul>
#foreach (var company in Model)
{
<li>#company.Name : #company.Description #Html.AnchorLink("Edit", "Update", new { company.id}) </li>
}
</ul>
Lets discuss how the flow of this application works
The Index Action gets triggered on companies.
We set the current link to companies in a Cookie
Then we set the Title in the ViewBag
We check the TempData for messages and put them into the ViewBag
Then we put the collection of companies into a Model and send it to the page.
Now razor kicks in and starts renders the page first
Then the layout renders and gets the Title value from the ViewBag
Then the header partial view renders and gets the currentlink value from a Cookie
We click the update button for a company
The update action runs
Gets the company from a database and sends it to the view in a Model
We change the title to update in the ViewBag
The page renders first and puts the company data on the form, from the Model
Then the layout renders and Gets the title value from the ViewBag
Then the header renders and gets the currentlink from a cookie (the value is still companies we did not have to change it)
Then we submit the form and add a message to the TempData
now we are back at the company list and we can get the success or failure message from the TempData
We used the Model to send Specific data to the view.
We used the ViewBag to send General data to the view and the layout.
We used TempData to pass data between actions without using parameters.
We used Cookies to Store data that wouldn't change for a while.
The correct is using ViewBag.Title, because it is on the context of your ViewBag property of your View while Page.Title is something that comes from asp.net webforms. That is the reason why Page.Title is null, there is no context for it.

Create reusable form contact component in asp.net mvc

I'm newbie at asp.net mvc, I'm trying to develop a reusable contact form component for asp.net mvc .
I have tryed to do it creating a PartialView with a form, I don't know if this is the better approach, for create a reusable component
My PartialView is
#model MyModel.ContactData
#using (Html.BeginForm("ContactForm", "ContactForm", FormMethod.Post)) {
<fieldset>
<p>
#Html.LabelFor(model => model.MailAddress)
#Html.EditorFor(model => model.MailAddress)
</p>
<p>
#Html.LabelFor(model => model.Message)
#Html.TextAreaFor(model => model.Message)
</p>
<input type="submit" value="Save" />
</fieldset>
}
The problems start with the controller, the controller is a specific controller for only this partialView.
public class ContactFormController : Controller
{
[HttpPost]
public ActionResult ContactForm(ContactData contactData)
{
if (ModelState.IsValid)
{
return PartialView("MessageSend");
}
return PartialView();
}
}
My problem is in case of some of the required fields are empty, in that case the controller returns only the partial view, not returning the partival view inside its parent context. I have tryed calling the PartialView from parent View as #Html.Partial, #Html.RenderAction, #Html.RenderPartial and the same occurs.
How can I return the partial view Inside it's parent Context? I have tried with
return View(ParentViewsName, contactData) but I dislike it because on form submitting it changes the url on address bar from /Contact to /ContactForm/ContactForm.
Perphaps I'm trying to create a reusable component with a wrong approach? It's better to update with ajax only the PartialView? Alternatives?
Thanks
From my understanding, you wish to display status message which is a partial view after user successfully submits the form. I think tempdata will be apt for this kind of situation.
public class ContactFormController : Controller
{
[HttpPost]
public ActionResult ContactForm(ContactData contactData)
{
if (ModelState.IsValid)
{
TempData["success"] = true;
return RedirectToAction("parentpage");
}
return View(contactData);
}
}
In parent page, check whether TempData["success"] is null and display the partial view "MessageSend".
Finally as Sundeep explains I have done this with ajax like this example Partial ASP.NET MVC View submit.
Thanks for your help.

MVC ASP.Net how do I add a second model to a view? i.e. Add a dropdown list to a page with a html grid?

I have been able to find lots of examples of adding a Dropdown list to a view but I need to add a dropdown list to a view that also has a Webgrid on it. This entails two different models and from what I see I can only have one per view.
The DDL will be filled from one model and the grid from the other.
I'm just trying to filter the displayed data in the grid with the data selected in the ddl.
Any examples or articles would be greatly appreciated.
TIA
Create a ViewModel that has the data for both your grid and your DropDownList. Use this ViewModel object as the model for your view.
See Steve Michelotti's post for different strategies on implementing the ViewModel pattern.
Something like this, for example:
public class MyViewModel
{
public List<Row> RowsForGrid { get; set; }
public SelectList ItemsForDropdown { get; set; }
}
Since you're trying to filter the displayed data in the grid, I'd do it this way:
In the main view I'd call a partial view. In your case the partial view will hold the DropDownList data. Something like this:
#Html.Partial("DropDownView", ViewBag.DropDownViewModel as DropDownViewModel)
In your controller action you'd fill the DropDownViewModel with the DropDownList data and would pass the DropDownViewModel to the ViewBag like this:
DropDownViewModel dropDownViewModel = new DropDownViewModel();
DropDownViewModel.Items = GetDropDownData(); // Fetch the items...
ViewBag.DropDownViewModel = dropDownViewModel;
ViewModel (DropDownViewModel.cs)
public class DropDownViewModel
{
public SelectList Items { get; set; }
}
Partial View (DropDownView.cshtml)
#model DropDownViewModel
#using (Html.BeginForm("YourControllerAction", "YourControllerName", FormMethod.Get))
{
#Html.Label("Search") #Html.DropDownList("YourDataId", Model.Items, String.Empty)
<input type="submit" value="Search" id="submit"/>
}
"YourDataId" will be a parameter for the action method and will contain the value selected by the user like this:
public virtual ActionResult Index(int? YourDataId, GridSortOptions sort)
{
...
}

Resources