I am new to ASP.NET MVC 3. I am trying to create a basic WebGrid to try and learn how this works. Currently, I have the following code:
#{
ViewBag.Title = "Home Page";
}
<h2>#ViewBag.Message</h2>
<p>
#{
var grid = new WebGrid();
}
#grid.GetHtml()
</p>
When I run this code, I receive an error that says: "A data source must be bound before this operation can be performed.". My question is, how do I bind this WebGrid to some client-side JSON. I don't have a back-end database. I'm just trying to learn about the WebGrid without having to wireup a database.
thanks!
As always in an ASP.NET MVC application you start with a view model:
public class MyViewModel
{
public int Foo { get; set; }
public string Bar { get; set; }
}
then a controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new[]
{
new MyViewModel { Foo = 1, Bar = "bar 1" },
new MyViewModel { Foo = 2, Bar = "bar 2" },
new MyViewModel { Foo = 3, Bar = "bar 3" },
};
return View(model);
}
}
and finally a corresponding view (~/Views/Home/Index.cshtml):
#model IEnumerable<MyViewModel>
#{
var grid = new WebGrid(Model);
}
#grid.GetHtml()
So as you can see the data source of the grid is actually the view model that the controller populated and passed to the view. The actual data could come from anywhere. It's the controller's responsibility though to populate the view model and pass it to the view.
And to learn more about the WebGrid control you may take a look at the following article. And here's another one.
Related
I am basically trying to display a dropdownlist on my data entry view, and the dropdownlist keeps giving me the error "An expression tree may not contain a dynamic operation". I have added "#Model MyModel" to the top of my view, but still can't get past this error. Does anyone have an idea of how to resolve this issue? I have a controller that looks like this
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
public class MyController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult EnterInfo()
{
GetUT myGetUT = new GetUT();
ViewBag.uts = GetOptions();
return View(myGetUT);
}
[HttpPost]
public ActionResult EnterInfo(GetUT myGetUT)
{
ViewBag.uts = GetOptions();
return View(myGetUT);
}
private List<UT> GetOptions()
{
List<UT> uts = new List<UT>();
uts.Add(new UT() { ID = 1, Name = "1st" });
uts.Add(new UT() { ID = 2, Name = "2nd" });
uts.Add(new UT() { ID = 3, Name = "3rd" });
uts.Add(new UT() { ID = 4, Name = "4th" });
return uts;
}
}
}
and a view that looks like
#Model MyModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<title>EnterInfo</title>
</head>
<body>
<div>
#Html.DropDownListFor(x => x.UTID, new SelectList(ViewBag.uts, "ID", "Name", Model.UTID))
Enter an Amount :-<input type="text" name="Amount" /><br />
<input type="submit" value="Submit Info" />
</div>
</body>
</html>
Thanks for all the help.
Well, ViewBag is a dynamic type, so I assume that is what it is complaining about. Try putting public List<UT> UTs { get; set; } as a property on MyModel and change your helper to use the UTs property from your model. Like this:
Controller:
public ActionResult EnterInfo()
{
GetUT myGetUT = new GetUT();
myGetUT.UTs = GetOptions();
return View(myGetUT);
}
View:
#Html.DropDownListFor(x => x.UTID,
new SelectList(Model.UTs, "ID", "Name", Model.UTID))`
Edit: If it isn't obvious, your view should be typed to a GetUT type (because that's what you are passing in to the View() function in the EnterInfo action) - I assume that's what you mean when you said #Model MyModel. If not, change it to #Model GetUT and put the property on the GetUT class.
Following is my model property
[Required(ErrorMessage = "Please Enter Short Desciption")]
[StringLength(200)]
public string ShortDescription { get; set; }
And following is my corresponding View code
#Html.TextAreaFor(model => model.Product.ShortDescription, new { cols = "50%", rows = "3" })
#Html.ValidationMessageFor(model => model.Product.ShortDescription)
And this is how it shows in the browser, the way i want.
Now, since there is a bug in Microsoft's MVC3 release, I am not able to validate and the form is submitted and produces the annoying error.
Please tell me the work around or any code that can be substituted in place of TextAreaFor. I can't use EditorFor, because with it, i can't use rows and cols parameter. I want to maintain my field look in the browser. Let me know what should be done in this case
In the controller action rendering this view make sure you have instantiated the dependent property (Product in your case) so that it is not null:
Non-working example:
public ActionResult Foo()
{
var model = new MyViewModel();
return View(model);
}
Working example:
public ActionResult Foo()
{
var model = new MyViewModel
{
Product = new ProductViewModel()
};
return View(model);
}
Another possibility (and the one I recommend) is to decorate your view model property with the [DataType] attribute indicating your intent to display it as a multiline text:
[Required(ErrorMessage = "Please Enter Short Desciption")]
[StringLength(200)]
[DataType(DataType.MultilineText)]
public string ShortDescription { get; set; }
and in the view use an EditorFor helper:
#Html.EditorFor(x => x.Product.ShortDescription)
As far as the rows and cols parameters that you expressed concerns in your question about, you could simply use CSS to set the width and height of the textarea. You could for example put this textarea in a div or something with a given classname:
<div class="shortdesc">
#Html.EditorFor(x => x.Product.ShortDescription)
#Html.ValidationMessageFor(x => x.Product.ShortDescription)
</div>
and in your CSS file define its dimensions:
.shortdesc textarea {
width: 150px;
height: 350px;
}
I'm experimenting with ASP.NET MVC3 and want to simply populate a dropdown list with data I get from a LINQ2SQL class, like so
controller (I know, Linq doesn't belong in the controller)
var allUsers = (from u in _userDataContext.Users
select u).ToList();
ViewBag.allUsers = allUsers.ToList();
return View();
view:
<select id="drop_heroes">
#foreach (var u in ViewBag.allUsers)
{
<option value="#u.pk_userid">#u.email</option>
}
</select>
That works fine, but I would like to use Razor #Html.Dropdownlist to create the same dropdown list, but can't find any info to make this work with Linq data.
I know, Linq doesn't belong in the controller
Then why are you using it in a controller? Anyway, at least it's fine that you know it.
Here's an example. As always in an ASP.NET MVC application you start by defining a view model which will represent the data that you need in the view. So in your case you need to display a dropdown so you define a list of users and a selected user id:
public class MyViewModel
{
public string SelectedUserId { get; set; }
public IEnumerable<SelectListItem> Users { get; set; }
}
then you define a controller action which will populate this view model from your repository and handle it to the view:
public ActionResult Index()
{
var model = new MyViewModel
{
Users = _userDataContext.Users.ToList().Select(x => new SelectListItem
{
Value = x.pk_userid.ToString(),
Text = x.email
})
}
return View(model);
}
and finally you will have a view which will be strongly typed to your view model and use HTML helpers to generate the dropdownlist:
#model MyViewModel
#using (Html.BeginForm())
{
#Html.DropDownListFor(x => x.SelectedUserId, Model.Users)
<button type="submit">OK</button>
}
Things to notice:
Usage of view models
Usage of a strongly typed view
Usage of strongly typed HTML helpers to generate markup such as form elements and input fields
Getting rid of weakly typed structures such as ViewBag
If you follow these simple rules you will see how much easier your life as an ASP.NET MVC developer will become.
I am creating a breadcrumb partial view which takes in a collection of title/URL. The collection will be generated in action methods and would have to be available on the breadcrumb partial view.
I tried couple of ways to get it done and this is one among such: http://goo.gl/rMFlp
But some how i could not get it working. All i get is an "Object reference not set to an instance of an object." Can you guys help me out?
{Updare}
Here is the code:
I created a Model class as follows
public class ShopModel
{
public Dictionary<string,string> Breadcrumb { get; set; }
}
Action Method
public ActionResult Index()
{
var breadcrumbCollection = new Dictionary<string,string>();
breadcrumbCollection.Add("/home","Home");
breadcrumbCollection.Add("/shop","Shop");
var model = new ShopModel() { Breadcrumb = breadcrumbCollection};
return View(model);
}
Model binding the view - Index
#Model NexCart.Model.Model.Custom.ShopModel
Finally here is the code on partial view:
<div>
#{
foreach (var item in #Model.Breadcrumb)
{
#item.Key
}
}
You haven't shown any code, so your question is impossible to answer. This being said here's how you could proceed. As always in an ASP.NET MVC application you start by defining a view model:
public class Breadcrumb
{
public string Title { get; set; }
public string Url { get; set; }
}
then you could write a controller action which will populate a collection of breadcrumbs and pass them to a partial view:
public class BreadcrumbController: Controller
{
public ActionResult Index()
{
// TODO: pull the breadcrumbs from somewhere instead of hardcoding them
var model = new[]
{
new Breadcrumb { Title = "Google", Url = "http://www.google.com/" },
new Breadcrumb { Title = "Yahoo", Url = "http://www.yahoo.com/" },
new Breadcrumb { Title = "Bing", Url = "http://www.bing.com/" },
};
return PartialView(model);
}
}
then you could have a corresponding partial view which will render this model (~/Views/Breadcrumb/Index.cshtml):
#model IEnumerable<Breadcrumb>
<ul>
#Html.DisplayForModel()
</ul>
and the corresponding display template (~/Views/Breadcrumb/DisplayTemplates/Breadcrumb.cshtml):
#model Breadcrumb
<li>
#Model.Title
</li>
Now all that's left is to include this child action somewhere using the Html.Action helper. For example you could do this in the _Layout if this breadcrumb is repeated on each page:
#Html.Action("Index", "Breadcrumb")
But obviously it could also be done in any view.
I have two classes, Vat and Product. Product has a property of IVat. I am trying to use editor templates in MVC to display a dropdown list of all the Vat objects when creating/editing a Product. For the dear life of me I cannot get this working.
I have the following code which displays the dropdown but it does not set the Vat for the Product when the form gets submitted.
Controller:
IList<IVatRate> vatRates = SqlDataRepository.VatRates.Data.GetAllResults();
ViewBag.VatRates = new SelectList(vatRates, "Id", "Description");
Add.cshtml
#Html.EditorFor(model => model.VatRate.Id, "VatSelector", (SelectList)ViewBag.VatRates)
VatSelector.cshtml
#model SelectList
#Html.DropDownList(
String.Empty /* */,
(SelectList)ViewBag.Suppliers,
Model
)
I would be grateful if anyone can shed some light on this or even point me to a good example on the web somewhere...I have been stuck with this for quite a few days now.
I would use strongly typed views and view models as it makes things so much easier rather than ViewBag.
So start with a view model:
public class VatRateViewModel
{
public string SelectedVatRateId { get; set; }
public IEnumerable<IVatRate> Rates { get; set; }
}
then a controller:
public class HomeController: Controller
{
public ActionResult Index()
{
var model = new VatRateViewModel
{
Rates = SqlDataRepository.VatRates.Data.GetAllResults()
};
return View(model);
}
[HttpPost]
public ActionResult Index(VatRateViewModel model)
{
// model.SelectedVatRateId will contain the selected vat rate id
...
}
}
View:
#model VatRateViewModel
#using (Html.BeginForm())
{
#Html.DropDownListFor(
x => x.SelectedVatRateId,
new SelectList(Model.Rates, "Id", "Description")
)
<input type="submit" value="OK" />
}
And if you wanted to use editor template for the VatRateViewModel you could define one in ~/Views/Shared/EditorTemplates/VatRateViewModel.cshtml:
#model VatRateViewModel
#Html.DropDownListFor(
x => x.SelectedVatRateId,
new SelectList(Model.Rates, "Id", "Description")
)
and then whenever somewhere you have a property of type VatRateViewModel you could simply:
#Html.EditorFor(x => x.SomePropertyOfTypeVatRateViewModel)
which would render the corresponding editor template.