MVC3 binding querystring parameter to deep object property - asp.net

My domain is setup similar to
public class Pagination
{
public int? Page { get; set; }
}
public class IndexViewModel
{
public Pagination Pagination { get; set; }
}
public class HomeController : Controller
{
public ActionResult Index(IndexViewModel model, Pagination pg, string page)
{
return View(model);
}
}
When I navigate to /?Page=5 I would expect 5 to be the value of model.Pagination.Page to be 5 also, however it appears MVC does not bind query parameters more than 1 layer deep.
What can do I do to change this?
Or is changing this setting up more trouble than it's worth? And I should just do
public class HomeController : Controller
{
public ActionResult Index(IndexViewModel model, Pagination pg, string page)
{
model.Pagination = pg;
return View(model);
}
}
*Note the triple parameters are there to illustrate that it won't fill IndexViewModel but it fills both of the other parameters since they're 0 or 1 layer deep.

Shouldn't your method signature be...
public ActionResult Index(int? page)
{
var model = new IndexViewModel{
Pagination = new Pagination { Page = page ?? 1 } };
if(page.HasValue)
model.Stuff = StuffGenerator
.GetStuff()
.Skip(page.Value * _pageSize)
.Take(_pageSize);
else
model.Stuff = StuffGenerator.GetStuff().take(_pageSize);
return View(model);
}
Your example sounds like a GET but looks like a POST.

Related

Displaying SQL Query Results in View

I'm new to MVC 5 with .net
Basically I'm just trying to get my bearings and I want to display some generic queries (disregard the fact that im using the master db, I just want to get the functions working right now). I'm using the authentication 2.0 which has an applicatindbcontext, but I created my own context but since I'm not really wanting to create a model (which could be the problem) I didn't know what to create for properties:
public class MasterModel : DbContext
{
public MasterModel() : base("MasterDatabaseConnection")
{ }
}
I created the controller like:
public class MasterController : Controller
{
private MasterModel db = new MasterModel();
// GET: Statistics
public ActionResult Index()
{
return View();
}
public ActionResult GetVersion()
{
string query = "SELECT ##VERSION AS Version";
IEnumerable<MasterModel> data = db.Database.SqlQuery<MasterModel>(query);
return View(data.ToList());
}
}
And finally I'm trying to figure out how to display the results in the view...and I'm completely lost (although it's possible I was lost in one of the previous steps).
#model IEnumerable<IdentitySample.Models.MasterModel>
#{
ViewBag.Title = "Index";
}
#WTF.Am.I.SupposedToPutHere
I've followed some tutorials where I've created CRUD style model view controllers, but I guess I'm not drawing the connection on how to just submit informational queries and display the results.
Create a Context:
public class MasterModel : DbContext
{
public MasterModel() : base("MasterDatabaseConnection")
{ }
public DbSet<MyModel> ModelOBJ { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<ModelOBJ>().ToTable("tblModelOBJ");
}
}
Create a Model:
Public cLass MyModel
{
public int ID {get;set;}
public string Name {get;set;}
}
Public cLass MyModelRepository
{
public List<MyModel> GetALlModelFromDB()
{
MasterModel md = new MasterModel();
return md.ModelTosend.toList();
}
}
In your Controller:
public ActionResult Index()
{
return View(new MyModelRepository().GetALlModelFromDB());
}
In your View:
#model IEnumerable<IdentitySample.Models.MyModel>
#{
ViewBag.Title = "Index";
}
#foreach(var item in Model)
{
#:<div>#item.ID #item.Name </div>
}

Transferring data entities from a DataService class to a view in MVC

I'm trying to learn MVC. I'm having some trouble understanding how to return data from my DataService class to my view. Here's the structure of my solution so far:
The solution contains two projects and a database. The first project is my DataService project that contains my Entity Model and my service class called AppDataService.
The second project is the website itself. It contains my HomeController, an Index view, and my inventory model which contains two models: An Item and the DB Context for Items called Catalog.
The goal of the application is to create a simple application that displays the inventory of a stock room and displays the information for a user. It's not for a homework assignment so there are no predefined objectives. I'm just trying to learn the MVC convention on my own. I realize that this is a pretty basic question, but I'm kind of at a dead end.
Here's my code:
AppDataServices:
public class AppDataService:IAppDataService
{
public Inventory GetItem(string srch)
{
Inventory item = null;
using (var data = new WCSDatabaseEntities())
{
item = data.Inventories.FirstOrDefault(x => x.Name == srch);
}
return item;
}
public List<Inventory> GetCatalog()
{
List<Inventory> catalog = null;
using (var data = new WCSDatabaseEntities())
{
catalog = data.Inventories.ToList();
}
return catalog;
}
public void Dispose()
{
}
}
My application's models:
public class Item
{
public int MediaId { get; set; }
public string Name { get; set; }
public int InStock { get; set; }
public decimal Price { get; set; }
public string Manufacturer { get; set; }
}
public class InventoryDbContext : DbContext
{
public DbSet<Item> Catalog { get; set; }
}
Currently, nothing I have tried has worked so my home controller's index action just returns the view, and the view currently doesn't accept a model. Can anyone help to explain how I take the returned entities and attach them to a model to send to the view? Thanks in advance! I realize this is a really basic question.
Edit: Here is the Home Controller.
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
}
At your most basic level you want something like:
public class HomeController : Controller
{
public ActionResult Index()
{
// Assuming you're not using an IoC container.
AppDataService appDataService = new AppDataService();
Inventory item = appDataService.GetItem("Albatross");
IndexViewModel model =
new IndexViewModel()
{
Name = item.Name
};
return View(model);
}
}
Create yourself a folder called /ViewModels/Home in the root of your MVC project and add a class called IndexViewModel:
public class IndexViewModel
{
public string Name { get; set; }
}
Then in your view (Index.cshtml):
#model MyNamespaceChangeMe.ViewModels.Home.IndexViewModel
<p>Here's your #Model.Name from the stock room.</p>

How to bind bropdown list in Razor View (If view is not bound with any model)

Can anybody suggest me how bind a dropdown list in MVC Razor view. I am using MVC 4. I have a view that is not bound with any model class.
public class Util {
public List<EmployeeType> GetEmpTypes() {
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
}
public class EmployeeType {
public int ID { get; set; }
public string Text { get; set; }
}
I have this sample code. I am new to MVC Now after this I don't know how to bind the collection returned by GetEmployeeTypes() Method to a dropdown list
Your class with method
public class Util {
public List<EmployeeType> GetEmpTypes() {
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
}
Your model class with properties
public class EmployeeType {
public int ID { get; set; }
public string Text { get; set; }
}
This is sample action
public ActionResult ViewName()
{
Util xxx=new Util();
List<SelectList> SelectedItems =new List<SelectList>();
List<EmployeeType> items =xxx.GetEmpTypes();
foreach (var t in items )
{
SelectListItem s = new SelectListItem();
s.Text = t.Text;
s.Value = t.ID;
SelectedItems.Add(s);
}
ViewBag.xxxxx= SelectedItems;
return view();
}
In View
#Html.DropDownList("xxxxx", new SelectList(ViewBag.xxxxx, "Text", "Value"))
This above code just like a key, i don't tested for that code ran successfully. you can get some idea for how to bind dropdown from my code.
I had a Class like this to get all EmployeeTypes
public class Util
{
public List<EmployeeType> GetEmpTypes()
{
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
}
public class EmployeeType
{
public int ID { get; set; }
public string Text { get; set; }
}
In Controller I have written code to get the List of Employee Types
Util obj = new Util();
var v = obj.GetEmpTypes();
ViewBag.EmployeeTypes = v;
return View();
In the View I have written code to bind dropdown.
#Html.DropDownList("EmployeeTypes",new SelectList(ViewBag.EmployeeTypes,"ID","Text"));
Thanks #Ramesh Rajendran ( Now I understood the concept to bind dropdown)
*strong text*you should create the model selectlist like here:
public static List<EmployeeType> GetEmpTypes() {
return (new List<EmployeeType>(){
new EmployeeType(){ID=101, Text="Permanent"},
new EmployeeType(){ ID=102, Text="Temporary"}
});
}
public static SelectList GetMyEmpTypes
{
get { return new SelectList(GetEmpTypes(), "ID", "Text"); }
}
then you access this method in dropdown list like
#Html.DropDownList("Name",yourProjectNameSpace.Util.GetMyEmpTypes())
when you will submit your form then it value bidden with Name get post to controller.
it is not necessary to bind with model class.you can receive the value on controller with the name that you have given in view like:
#Html.DropDownList("Name",yourProjectNameSpace.YourClass.GetEmpTypes())
Now you can recive the name value at controller like:
public ActionResult test(String Name)
{
return view();
}
and make your method static i.e GetEmpTypes() so that you can access it from view.

How to make simple calculations using model items and an input from a form in ASP.net MVC 3?

Am new to programming and ASP.net MVC 3 so don't be surprised by my lack of knowledge on this.. Okay, I want to multiply two decimals, One decimal comes from the form that a user fills and the other decimal comes from the Model class (gets it from the database).
I have two Model classes called RATE & PROJECTMATERIAL . The RATE class has an item called Amount that states the amount of a Rate and the PROJECTMATERIAL class has an item quantity. The classes are related and i want to be able to say variable1 = quantity*Rates.amount and return variable1 to the my Index, Delete, Details views. I don't want to store variable1 to my database but i just want to display in my views.....but i don't know how and where to do it
Code from Project material class..
public class ProjectMaterial
{
public int ProjectMaterialID { get; set; }
[Required]
[Display(Name = "Scope Name")]
public int? ScopeID { get; set; }
[Required]
[Display(Name = "Rate Code")]
public int? RateID { get; set; }
[Required]
[Display(Name = "Quantity")]
public decimal Quantity { get; set; }
public virtual Scope Scopes { get; set; }
public virtual Rate Rates { get; set; }
}
Code from scope class..
public class Rate
{
public int RateID { get; set; }
[Required]
[Display(Name = "Rate Code")]
public int RateCode { get; set; }
[Required]
[Display(Name = "Unit")]
public string Unit { get; set; }
[Required]
[Display(Name = "Description")]
public string Description { get; set; }
[Required]
[Display(Name = "Amount")]
public decimal Amount { get; set; }
public virtual ICollection<ProjectMaterial> ProjectMaterials { get; set; }
}
Code from project controller class...
public class ProjectMaterialController : Controller
{
private ContructorContext db = new ContructorContext();
//
// GET: /ProjectMaterial/
public ViewResult Index()
{
var projectmaterials = db.ProjectMaterials.Include(p => p.Scopes).Include(p => p.Rates);
return View(projectmaterials.ToList());
}
//
// GET: /ProjectMaterial/Details/5
public ViewResult Details(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
return View(projectmaterial);
}
//
// GET: /ProjectMaterial/Create
public ActionResult Create()
{
ViewBag.ScopeID = new SelectList(db.Scopes, "ScopeID", "ScopeName");
ViewBag.RateID = new SelectList(db.Rates, "RateID", "Unit");
return View();
}
//
// POST: /ProjectMaterial/Create
[HttpPost]
public ActionResult Create(ProjectMaterial projectmaterial)
{
if (ModelState.IsValid)
{
db.ProjectMaterials.Add(projectmaterial);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ScopeID = new SelectList(db.Scopes, "ScopeID", "ScopeName", projectmaterial.ScopeID);
ViewBag.RateID = new SelectList(db.Rates, "RateID", "Unit", projectmaterial.RateID);
return View(projectmaterial);
}
//
// GET: /ProjectMaterial/Edit/5
public ActionResult Edit(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
ViewBag.ScopeID = new SelectList(db.Scopes, "ScopeID", "ScopeName", projectmaterial.ScopeID);
ViewBag.RateID = new SelectList(db.Rates, "RateID", "Unit", projectmaterial.RateID);
return View(projectmaterial);
}
//
// POST: /ProjectMaterial/Edit/5
[HttpPost]
public ActionResult Edit(ProjectMaterial projectmaterial)
{
if (ModelState.IsValid)
{
db.Entry(projectmaterial).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ScopeID = new SelectList(db.Scopes, "ScopeID", "ScopeName", projectmaterial.ScopeID);
ViewBag.RateID = new SelectList(db.Rates, "RateID", "Unit", projectmaterial.RateID);
return View(projectmaterial);
}
//
// GET: /ProjectMaterial/Delete/5
public ActionResult Delete(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
return View(projectmaterial);
}
//
// POST: /ProjectMaterial/Delete/5
[HttpPost, ActionName("Delete")]
public ActionResult DeleteConfirmed(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
db.ProjectMaterials.Remove(projectmaterial);
db.SaveChanges();
return RedirectToAction("Index");
}
Thanx in advance guys!! really need your help.
Seeing as you say you're new to MVC, I've given you a few options and explained which is best and why, because it's better to understand now so you don't get in to bad habits, especially if you start building larger projects.
You don't necessarily need to create a variable, because you can do that calculation in your view. Because you are passing the domain model directly to the view you can do (in razor):
#(Model.Quantity * Model.Rates.Amount)
Although this is the easiest option I wouldn't necessarily recommend this as views should be dumb - see ASP.NET MVC: How dumb should my view be?.
Another option is to do the calculation in the controller and pass the value in the ViewBag, e.g.:
public ViewResult Details(int id)
{
ProjectMaterial projectmaterial = db.ProjectMaterials.Find(id);
ViewBag.Price = projectmaterial.Quantity * projectmaterial.Rates.Amountl
return View(projectmaterial);
}
Then you could use it in your view like:
#ViewBag.Price
Again, this is easy but I wouldn't recommend it, as ViewBag isn't strongly typed - see Is using ViewBag in MVC bad?.
You could put a property on your ProjectMaterial class like, which is a neat solution.
public decimal Price
{
get
{
return Quantity * Rates.Amount;
}
}
However, if Price is a property that is only ever used within your views (ie you just display it) then it probably shouldn't be in your domain model, as your domain model is just that - storing and accessing the raw data.
Maybe the best way is to create a viewmodel specific to your view (see http://stephenwalther.com/blog/archive/2009/04/13/asp.net-mvc-tip-50-ndash-create-view-models.aspx) with a Price propert. This means that the property is only used where it is needed, the domain model remains just that, your view remains dumb and your domain model is not exposed to your view. See Why Two Classes, View Model and Domain Model? also for a good explanation of view models
You could add a property to your ProjectMaterial model:
public decimal Price
{
get
{
return Quantity * Rates.Amount;
}
}
You might want to have a model function with instances of your self.rate, and self.material items passed on from your views. Or otherwise you can individually calculate the values of the multiplication in each view.
Either way, you should be able to store the copy over the value of multiplication (variable1) in the view's bag, and pass it onto each view without having to save it in the DB.
ViewBag.variable1 = rate*material
return View()
#(int.Parse(variable) * your value)
Additional to all the answers you can use Data Format String in model class, and Html Helper in View to maintain formatting in displayed results for numeric types, by modifying returned attribute in the Controller.
The purpose of applying the formatting in the model class, and the value transformation in the controller and keeping the view standard, is to achieve separation of concerns (SoC) for easier maintenance, and control over the code.
Consider this example:
Products Class Property
[Display(Name = "Max Disc %")]
[DisplayFormat(DataFormatString = "{0:P1}", ApplyFormatInEditMode = true)]
public decimal MaxDiscountRate { get; set; }
Products Controller
[HttpGet]
public ActionResult Details(int id)
{
if (id == 0)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Products products = _uow.Products.GetById(id);
if (products == null)
{
return HttpNotFound();
}
else
{
products.MaxDiscountRate /= 100;
}
return View(products);
}
Products Details View
<div class="detail">
<h5 class="text-teal">#Html.DisplayNameFor(model => model.MaxDiscountRate)</h5>
<span class="text-peru">#Html.DisplayFor(model => model.MaxDiscountRate)</span>
</div>

Gallery Model with Picture and Comments in MVC3

I've just learnt how to upload pictures and bring them in view Model.
Now I'm trying to Add comments to the pictures. That means a picture can have more comments.
So I created 2 Tables, called "Gallery" and "Comment". They are related by 'One to Many'..
My model looks like that..
public class GalleryEntries
{
public List Entries { get; set; }
}
public class GalleryEntry
{
public Gallery GalleryImage { get; set; }
public List Comments { get; set; }
}
And the controller looks so..
GalleryDataContext GalleryDB = new GalleryDataContext();
public ActionResult Index()
{
GalleryEntries model = new GalleryEntries();
GalleryEntries galleryentries = new GalleryEntries();
foreach (Gallery gallery in GalleryDB.Galleries)
{
GalleryEntry galleryentry = new GalleryEntry();
galleryentry.Comments = GalleryDB.Comments.Where(c => c.BildID == gallery.ImageID).ToList();
galleryentry.GalleryImage = gallery;
galleryentries.Entries.Add(galleryentry);
}
return View(model);
}
But it doesn't work. :(
It displays "Object reference not set to an instance of an object" at the line where "galleryentries.Entries.Add(galleryentry) stands.. How can I solve this problem?
I think the problem is that you don't initialize the GalleryEntries.Entries property anywhere ... so you're attempting to add galleryentry to a List that does not exist yet, hence the NullReferenceException.
You could initialize Entries in the constructor:
public class GalleryEntries
{
public IList<GalleryEntry> Entries { get; set; }
public GalleryEntries() {
Entries = new List<GalleryEntry>();
}
}

Resources