I am trying to learn MVC. I had a very simple requirement that I wanted to insert commas in number displayed in a table. This is what I have.
Model
public partial class PACKAGE
{
public string PACKAGEID { get; set; }
[UIHint("withcommas")]
public Nullable<long> FILESIZE { get; set; }
}
Views\Shared\DisplayTemplates\withcommas.cshtml
#Model withcommas
#{
<span>[#Model.ToString("#,##0")]</span>
}
I did want to add the sqare brackets around it.
Views\Home\Packages.cshtml
#Html.DisplayFor(modelItem => item.FILESIZE)
What I am getting on the display is "2287097 withcommas [2,287,097];"
I do not understand why the original number as well as name of the hint is showing up in addition to the formatted number. I do not understand why there is an extra semicolon at the end.
Related
I have a lot of data that needs to be passed from a controller to a view and I am trying to use strongly typed View Models where possible.
Take an example where you have a database of loads of people - We want to edit a person whilst also presenting a list of everyone with the same surname.
public class person
{
public string ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class testviewmodel
{
public List<person> people { get; set; }
public person newperson { get; set; }
}
I can't use testviewmodel as the model for the post because there is a lot more going on in the form/data. I have managed to build a model that contains nearly all the form data, other than the ones from the View Model.
I generate some items in the form via:
<input asp-for="newperson.Firstname" class="form-control"/>
This in return generates:
<input class="form-control" disabled type="text" id="newperson_Firstname" name="newperson_Firstname" value="xxxx" />
However, I have tried adding newperson_Firstnameto my model alongside quite a few other combinations, and, I am just not able to see the data.
Can anyone please assist and let me know what I am doing wrong - or, should I just be adjusting the view model to be more fit for purpose?
...Lastly, is there any equivalent of var_dump($_REQUEST);? At the moment, I'm adding breakpoints and trying to open up different items within Locals, but, it's trial and error and taking ages... I'm just trying to find where the form is!
You shouldn't need to dig around in the Request object. If you pass an instance of your ViewModel to your post action, model binding will take care of populating the Person property automatically:
[HttpPost]
public IActionResult Edit(TestviewModel model)
{
var person = model.Person; // add a breakpoint here, should represent the posted values
}
I am teaching myself asp .net mvc3.
I have a partial view which uses various models and lookup type db. I want to keep it strongly typed and use it in multiple places but I am not sure how to implement it.
The example below should explain it better. This question might get a bit long and I appreciate your patience.
The partial view basically gives a small description of the property. A snippet of the ‘_PropertyExcerptPartial’ is below:
#model Test.ViewModels.PropertyExcerptViewModel
<div>
<h3>#Html.DisplayFor(model => model.Property.NoOfBedrooms) bedroom #Html.DisplayFor(model => model.FurnitureType.FurnitureTypeDescription) flat to Rent </h3>
…
</div>
I want to keep this partial view strongly typed and use it in multiple places. The model that it is strongly typed to is as follows:
public class PropertyExcerptViewModel
{
public Property Property { get; set; }
public FurnitureType FurnitureType { get; set; }
}
The two 2 database that this model looks up is as follows:
public class Property
{
public int PropertyId {get; set; }
...
public int NoOfBedrooms {get; set;}
public int FurnishedType { get; set; }
...
}
public class FurnishedType
{
public int FurnishedTypeId { get; set; }
public string FurnishedTypeDescription { get; set; }
}
The furnished type database is basically just a lookup table with the following data:
1 - Furnished
2 - Not Furnished
3 - Part Furnished
4 - Negotiable
I have many such lookups in that I only store an int value in the property database which can be used to look up the description. These databases are not linked to property database and the value of furniture type is read via a function GetFurnitureType(id). I pass stored int value of Property.FurnitureType as the id.
However, I encounter a problem when I try to use this partial view as I am not sure how to pass these multiple models from a view to partial view.
Say I am trying to create an ‘added property’ page. This page basically list the properties added by the logged in user. To facilitate this, I have created another function called GetAddedProperties(userId) that return the properties added by a particular user. In the ‘added property’ view, I can call a foreach function to loop through all the properties returned by GetAddedProperties and display the _PropertyExcerptPartial. Something like this:
<div>
#foreach (var item in //Not sure what to pass here)
{
#Html.Partial("_PropertyExcerptPartial",item)
}
</div>
However, I can’t use the partial view to display information as it will display the int value of furniture type stored in the property database and I am not sure how to get the corresponding FurnitureTypeDescription and pass it to the partial view from the ‘added property’ page.
Any help would be appreciated. Thanks a lot!
You should start by designing a real view model, not some class that you suffix its name with ViewModel and stuff your domain models inside. That's not a view model.
So think of what information you need to work with in your view and design your real view model:
public class PropertyExcerptViewModel
{
public int NoOfBedrooms { get; set; }
public string FurnishedTypeDescription { get; set; }
}
and then adapt your partial to work with this view model:
#model Test.ViewModels.PropertyExcerptViewModel
<div>
<h3>
#Html.DisplayFor(model => model.NoOfBedrooms)
bedroom
#Html.DisplayFor(model => model.FurnitureTypeDescription)
flat to Rent
</h3>
...
</div>
OK, now that we have a real view model let's see how we could populate it. So basically the main view could be strongly typed to a collection of those view models:
#model IEnumerable<Test.ViewModels.PropertyExcerptViewModel>
<div>
#foreach (var item in Model)
{
#Html.Partial("_PropertyExcerptPartial", item)
}
</div>
and the last bit of course is the main controller that will do all the db querying and building of the view model that will be passed to the main view:
[Authorize]
public ActionResult SomeAction()
{
// get the currently logged in username
string user = User.Identity.Name;
// query the database in order to fetch the corresponding domain entities
IEnumerable<Property> properties = GetAddedProperties(user);
// Now let's build the view model:
IEnumerable<PropertyExcerptViewModel> vm = properties.Select(x => new PropertyExcerptViewModel
{
NoOfBedrooms = x.NoOfBedrooms,
FurnishedTypeDescription = GetFurnitureType(x.FurnishedType).FurnishedTypeDescription
});
// and finally pass the view model to the view
return View(vm);
}
Be careful with the lazy nature of EF if that is the ORM that you are using in order not to fall into the SELECT N + 1 trap.
I have a ‘Create’ page in my MVC3 application that has 4 input fields that are all required. I also have an ‘Edit’ page in which 3 of these 4 fields can be edited. I do not want to display the 4th field and want to maintain it at its initial value (the field is the date that the entry was created ).
I mark the 4th field as [Required] in the model then this causes the model to be declared as invalid in post action method of the Edit field. If I omit the [Required] annotation then someone can create a user with a null value for this 4th field.
How can I get around this problem?
Model Code:
[Required]
[DisplayName("User Name")]
public string UserName { get; set; }
[Required]
public string Role { get; set; }
[Required]
[DataType(DataType.Date)]
[DisplayName("Insert Date")]
public DateTime? InsertDate { get; set; }
[Required]
[DisplayName("Active")]
public bool ActiveInd { get; set; }
Controller Code:
public ActionResult Edit(int id, ZUserRoleModel mod)
{
if (ModelState.IsValid)
{
// code removed
return RedirectToAction("Index");
}
return View(mod);
}
You can make that field as hidden in edit mode.
#Html.HiddenFor(x => x.EntryDate)
Not sure if you still need an answer for this, but what you need to do in order for the
#Html.HiddenFor(x => x.EntryDate )
to work, is pass an existing model into view. So let's assume that your action for getting the user data looks like this. ( You did not supply it, so I am not sure if this is right )
Public ActionResult GetUser(int UserID)
{
ZUserRoleModel model = new ZUserRoleModel(UserID);
// Maybe this could go to your database and gather user
// It would populate the correct data into a model object
return View("Edit", model);
}
With combination of the hidden field, your view will be populated with the existing user information, and the hidden field will be populated with data, and it will be passed to your edit action.
NOTE: I wrote this without any kind of testing, but it should still work, or at the very least, I hope it points you in the right direction if you still need assistance.
You can use fluentvalidation: http://fluentvalidation.codeplex.com/
Have a rule that's something like
RuleFor(user => user.field4).NotEmpty().When(ViewContext.Controller.ValueProvider.GetValue("action").RawValue <> "edit")
How would I display data from the following database entity in a format that looks like a table:
public class Attendance
{
public int AttendanceID { get; set; }
public int CourseID { get; set; }
public int StudentID { get; set; }
public int AttendanceDay { get; set; }
public bool Present { get; set; }
public virtual Course Course { get; set; }
public virtual Student Student { get; set; }
}
I would want to find all rows in the Attendance db entry that had CourseID == x; So I would use something like:
AttendanceData = Attendance.Where(s => s.CourseID == x); // I think
Then I would need to be able to sort this information in my view to display it in a way that makes sense. I would want to have a data on screen with all of the present/not present values sorted in a table with StudentIDs listed on the left and AttendanceDays listed accross the top.
How would I sort and display this information?
UPDATE:
Using the following code (along with Mvc WebGrid) - I can get a grid of some sort to appear in my view.
Controller:
IEnumerable<Attendance> model = db.Attendance.Where(s => s.CourseID == 4);
return View(model);
View:
#model IEnumerable<MyProject.Models.Attendance>
<div>
#{
var grid = new WebGrid(Model, defaultSort: "Name");
}
#grid.GetHtml()
</div>
However, the grid is not organized in a manner that is useful for my needs.
I want the top of my displayed table to read:
Day 1 | Day 2 | Day 3 | etc until the max value of "Attendance Day" (which is dictated at the creation of a Course that a student signs up for).
I want the left side of the displayed table to read:
Student ID 1
Student ID 5
Student ID 6
Student ID etc . . until all of the students within the data set have been displayed.
I think I need to use something along the lines of this in my controller:
var model = from s in db.Attendance
where s.CourseID == 4
group s.AttendanceDay by s.StudentID into t
select new
{
StudentID = t.Key,
Days = t.OrderBy(x => x)
};
return View(model);
But I need an IEnumerable<> returned to my view using Mvc WebGrid -- I am getting somewhere, just still a little lost along the way. Can I get a nudge in the right direction?
For a fairly typical set of requirements, it sounds like this would be a good candidate for the ASP.NET WebGrid. It's flexible, allows for paging, sorting, formatting, etc. I've used it for a few projects and works just like any of the other HTML helpers that you're probably used to in ASP.NET MVC.
Here's a good starting place.
How do I pass variables to multiple partial views within a view? My idea is that every partial view will make up a different field in a form, and I plan on using dynamically created DOM objects with each partial view. So I need to pass in 3 parameters. An ID (to uniquely identify each DOM object), and its particular controller and action. How would I go about doing this in a view?
For example, I want to do something along the lines of...
#Html.Partial("_BookField", Model, 1, "book", "updateauthor")
#Html.Partial("_BookField", Model, 2, "book", "updatetitle")
#Html.Partial("_BookField", Model, 3, "book", "updatepublisher")
Is there a way to do this without adding additional attributes in the model?
Edit: After conferring with one of my coworkers, he also brought up a point that I'd like clarification on. He suggested that what I'm doing, which is introducing controller/action logic in the view is breaking the MVC concept. But things like ActionLinks, you have to put in the controller and action in an actionlink for it to be able to do something. Is what I'm trying to do considered breaking the MVC paradigm?
You use view models of course:
public class SubViewModel
{
public int Id { get; set; }
public string Book { get; set; }
public string Author { get; set; }
}
and then have your main view model different properties of this SubViewModel:
public class MyMainViewModel
{
public SubViewModel Sub1 { get; set; }
public SubViewModel Sub2 { get; set; }
public SubViewModel Sub3 { get; set; }
}
and then simply:
#Html.Partial("_BookField", Model.Sub1)
#Html.Partial("_BookField", Model.Sub2)
#Html.Partial("_BookField", Model.Sub3)
Of course it is the now the controller action responsibility to fill those view models (as always). And if you use editor/display templates your code might be even simpler, just like this:
#Html.DisplayFor(x => x.Sub1)
#Html.DisplayFor(x => x.Sub2)
#Html.DisplayFor(x => x.Sub3)
and because this strangely looks to me like a collection, well, you could use a collection:
public class MyMainViewModel
{
public SubViewModel[] Subs { get; set; }
}
and then simply:
#Html.DisplayFor(x => x.Subs)