ASP.NET MVC change model data type in before send to view - asp.net-mvc-3

I used Linq to Entity, for fetch a model from DB
var works = db.Work.Where(a => a.StartDate == DateTime.Now).ToList();
this model contain a DateTime that I want to change it to string before send it to view
beacuase need to show it as a persianDate Time,
like this :
foreach (var item in workslist)
{
item.StartDate = "1391/01/01"; //Just For Exapmle as you know this won't work
}
return View(workslist);
So is there any way to change a data type in a strongly typed model? or other way to do this except save DateTime as String in my DB

You can use the [DisplayFormat] attribute with EditorFor/DisplayFor helpers to format the data.
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:yyyy/mm/dd}")]
public DateTime StartDate { get; set; }
Then in view:
#Html.EditorFor(m => m.StartDate)
OR, you can also consider to define separate ViewModel for your 'Work' domain model. Though this approach results in more code, it's provide more flexibility and considered as good practice.
Here is sample code:
public class Work
{
public DateTime StartDate {get;set;}
}
public class WorkViewModel
{
public WorkViewModel()
{
}
public string StartDate { get; set; }
public static WorkViewModel Map(Work domainModel)
{
return new WorkViewModel() {
//Apply your Date format logic
StartDate = domainModel.StartDate.ToString("yyyy/MM/dd")
};
}
}
In action method:
var works = db.Work.Where(a => a.StartDate == DateTime.Now).ToList();
var workViewModels = new List<WorkViewModel>(works.Count);
foreach (var work in works)
workViewModels.Add(WorkViewModel.Map(work));
return View(workViewModels);

you can have a function in your controller to change datetime to string
public string changeDateTimeToPersianString ( DateTime time)
{
// your code
}
then you can call this function from your View.
in Razor something like this
#changeDateTimeToPersianString(workslistitem.StartDate)

Related

mvc dropdownlist not showing data value

I'm having an issue displaying data from the database into drop-downlist.
controller
TowinsEntities db = new TowinsEntities();
public ActionResult TMakes()
{
//T_Make make_db = new Models.T_Make();
ViewBag.carMaker = new SelectList(db.T_Make, "Make");
return View();
}
view
#Html.DropDownList("carMaker", "Select Make")
model
public partial class T_Make
{
public string Make { get; set; }
}
The output of a view is:
You need to overload your DropDownList with the string field names you want for value/display. You're only passing the model and selected value. I guess you'd use Make for both value and display (though, most people would use an ID for a value)
ViewBag.carMaker = new SelectList(db.T_Make, "Make","Make");
https://learn.microsoft.com/en-us/dotnet/api/system.web.mvc.selectlist.-ctor?view=aspnet-mvc-5.2#System_Web_Mvc_SelectList__ctor_System_Collections_IEnumerable_System_String_System_String_

Single property not getting bound on HttpPost

I'm working on the first MVC3 project at our company, and I've hit a block. No one can seem to figure out what's going on.
I have a complex Model that I'm using on the page:
public class SpaceModels : List<SpaceModel> {
public bool HideValidation { get; set; }
[Required(ErrorMessage=Utilities.EffectiveDate + Utilities.NotBlank)]
public DateTime EffectiveDate { get; set; }
public bool DisplayEffectiveDate { get; set; }
}
In the Controller, I create a SpaceModels object with blank SpaceModels for when Spaces get combined (this would be the destination Space).
// Need a list of the models for the View.
SpaceModels models = new SpaceModels();
models.EffectiveDate = DateTime.Now.Date;
models.DisplayEffectiveDate = true;
models.Add(new SpaceModel { StoreID = storeID, SiteID = siteID, IsActive = true });
return View("CombineSpaces", models);
Then in the View, I am using that SpaceModels object as the Model, and in the form making a TextBox for the Effective Date:
#model Data.SpaceModels
#using (Html.BeginForm("CombineSpaces", "Space")) {
<div class="EditLine">
<span class="EditLabel LongText">
New Space Open Date
</span>
#Html.TextBoxFor(m => m.EffectiveDate, new {
size = "20",
#class = "datecontrol",
// Make this as a nullable DateTime for Display purposes so we don't start the Calendar at 1/1/0000.
#Value = Utilities.ToStringOrDefault(Model.EffectiveDate == DateTime.MinValue ? null : (DateTime?)Model.EffectiveDate, "MM/dd/yyyy", string.Empty)
})
#Html.ValidationMessageFor(m => m.EffectiveDate)
</div>
<hr />
Html.RenderPartial("_SpaceEntry", Model);
}
The Partial View that gets rendered iterates through all SpaceModels, and creates a containing the Edit fields for the individual SpaceModel objects. (I'm using the List to use the same Views for when the Spaces get Subdivided as well.)
Then on the HttpPost, the EffectiveDate is still back at it's DateTime.MinValue default:
[HttpPost]
public ActionResult CombineSpaces(SpaceModels model, long siteID, long storeID, DateTime? effectiveDate) {
// processing code
}
I added that DateTime? effectiveDate parameter to prove that the value when it gets changed does in fact come back. I even tried moving the rendering of the TextBox into the _SpaceEntry Partial View, but nothing worked there either.
I did also try using the #Html.EditorFor(m => m.EffectiveDate) in place of the #Html.TextBoxFor(), but that still returned DateTime.MinValue. (My boss doesn't like giving up the control of rendering using the #Html.EditorForModel by the way.)
There has to be something simple that I'm missing. Please let me know if you need anything else.
Looking at the source code for DefaultModelBinder, specifically BindComplexModel(), if it detects a collection type it will bind the individual elements but will not attempt to bind properties of the list object itself.
What model binding does is attempt to match the names of things or elements in the view to properties in your model or parameters in your action method. You do not have to pass all of those parameters, all you have to do is add them to your view model, then call TryUpdateModel in your action method. I am not sure what you are trying to do with SpaceModel or List but I do not see the need to inherit from the List. Im sure you have a good reason for doing it. Here is how I would do it.
The view model
public class SpacesViewModel
{
public DateTime? EffectiveDate { get; set; }
public bool DisplayEffectiveDate { get; set; }
public List<SpaceModel> SpaceModels { get; set; }
}
The GET action method
[ActionName("_SpaceEntry")]
public PartialViewResult SpaceEntry()
{
var spaceModels = new List<SpaceModel>();
spaceModels.Add(
new SpaceModel { StoreID = storeID, SiteID = siteID, IsActive = true });
var spacesVm = new SpacesViewModel
{
EffectiveDate = DateTime.Now,
DisplayEffectiveDate = true,
SpaceModels = spaceModels
};
return PartialView("_SpaceEntry", spacesVm);
}
The POST action method
[HttpPost]
public ActionResult CombineSpaces()
{
var spacesVm = new SpacesViewModel();
// this forces model binding and calls ModelState.IsValid
// and returns true if the model is Valid
if (TryUpdateModel(spacesVm))
{
// process your data here
}
return RedirectToAction("Index", "Home");
}
And the view
<label>Effective date: </label>
#Html.TextBox("EffectiveDate", Model.EffectiveDate.HasValue ?
Model.EffectiveDate.Value.ToString("MM/dd/yyyy") : string.empty,
new { #class = "datecontrol" })
Sometimes you need to explicitly bind form data using hidden fields such as
#Html.HiddenField("EffectiveDate", Model.EfectiveDate.)
In order to bind the properties of the SpaceModel object you can add individual properties such as SiteID to the view model or add a SpaceModel property for a single SpaceModel. If you want to successfully bind a complex model, add it as a Dictionary populated with key-value pairs rather than a List. You should then add the dictionary to the view model. You can even add a dictionary of dictionaries for hierarchical data.
I hope this helps :)

implementing dropdownlist in asp.net mvc 3

I am teaching myself asp .net mvc3. I have researched a lot but the more I read the more confused I become. I want to create a page where users can register their property for sale or rent.
I have created a database which looks like this:
public class Property
{
public int PropertyId { get; set; }
public int PropertyType { get; set; }
ยทยทยท
public int Furnished { get; set; }
...
}
Now, I want dropdownlistfor = PropertyType and Furnished.
Property type would be
1 Flat
2 House
3 Detached House
...
Furnished would be:
1 Furnished
2 UnFurnished
3 PartFurnished
...
Now, I am really not sure where to keep this information in my code. Should I have 2 tables in my database which store this lookup? Or should I have 1 table which has all lookups? Or should I just keep this information in the model?
How will the model bind to PropertyType and Furnished in the Property entity?
Thanks!
By storing property types and furnished types in the database, you could enforce data integrity with a foreign key, rather than just storing an integer id, so I would definitely recommend this.
It also means it is future proofed for if you want to add new types. I know the values don't change often/will never change but if you wanted to add bungalow/maisonette in the future you don't have to rebuild and deploy your project, you can simply add a new row in the database.
In terms of how this would work, I'd recommend using a ViewModel that gets passed to the view, rather than passing the database model directly. That way you separate your database model from the view, and the view only sees what it needs to. It also means your drop down lists etc are strongly typed and are directly in your view model rather than just thrown into the ViewBag. Your view model could look like:
public class PropertyViewModel
{
public int PropertyId { get; set; }
public int PropertyType { get; set; }
public IEnumerable<SelectListItem> PropertyTypes { get; set; }
public int Furnished { get; set; }
public IEnumerable<SelectListItem> FurnishedTypes { get; set; }
}
So then your controller action would look like:
public class PropertiesController : Controller
{
[HttpGet]
public ViewResult Edit(int id)
{
Property property = db.Properties.Single(p => p.Id == id);
PropertyViewModel viewModel = new PropertyViewModel
{
PropertyId = property.Id,
PropertyType = property.PropertyType,
PropertyTypes = from p in db.PropertyTypes
orderby p.TypeName
select new SelectListItem
{
Text = p.TypeName,
Value = g.PropertyTypeId.ToString()
}
Furnished = property.Furnished,
FurnishedTypes = from p in db.FurnishedTypes
orderby p.TypeName
select new SelectListItem
{
Text = p.TypeName,
Value = g.FurnishedTypeId.ToString()
}
};
return View();
}
[HttpGet]
public ViewResult Edit(int id, PropertyViewModel propertyViewModel)
{
if(ModelState.IsValid)
{
// TODO: Store stuff in the database here
}
// TODO: Repopulate the view model drop lists here e.g.:
propertyViewModel.FurnishedTypes = from p in db.FurnishedTypes
orderby p.TypeName
select new SelectListItem
{
Text = p.TypeName,
Value = g.FurnishedTypeId.ToString()
};
return View(propertyViewModel);
}
}
And your view would have things like:
#Html.LabelFor(m => m.PropertyType)
#Html.DropDownListFor(m => m.PropertyType, Model.PropertyTypes)
I usually handle this sort of situation by using an enumeration in code:
public enum PropertyType {
Flat = 1,
House = 2,
Detached House = 3
}
Then in your view:
<select>
#foreach(var val in Enum.GetNames(typeof(PropertyType)){
<option>val</option>
}
</select>
You can set the id of the option equal to the value of each item in the enum, and pass it to the controller.
EDIT: To directly answer your questions:
You can store them as lookups in the db, but for small unlikely to change things, I usually just use an enum, and save a round trip.
Also look at this approach, as it looks better than mine:
Converting HTML.EditorFor into a drop down (html.dropdownfor?)

FormCollection System.Web.Mvc.ModelErrorCollection

csharp newpie here, i have the following controller action that processes a strongly typed view form, some values im processing manually from fromCollection, it they are empty then i get this error:
{ Key = carCount , Errors = System.Web.Mvc.ModelErrorCollection }
but if there are incoming values e.g. "0", "1" etc then its fine!
[HttpPost]
public ActionResult create(Trip trip, FormCollection collection)//Trip trip
{
trip.carCount = TryToParse(collection["carCount"]);//int
trip.busCount = TryToParse(collection["busCount"]);//int
trip.truckCoun = TryToParse(collection["truckCount"]);//int
var errors = ModelState
.Where(x => x.Value.Errors.Count > 0)
.Select(x => new { x.Key, x.Value.Errors })
.ToArray();
foreach (var error in errors)
{
System.Diagnostics.Debug.WriteLine(error);
}
more code................
This is the method to convert string to int, which works perfectly fine:
private int TryToParse(string value)
{
if (value.Trim() == "" || value.Trim() == null) value = "0";
int number;
bool result = int.TryParse(value, out number);
return number;
}
Any thoughts?
thanks
The default model binder which runs before your action sees that you have this Trip model as parameter to your action and tries to set its properties from the request. Now because you have defined those 3 properties as integers if the Request contains empty values for them, during the binding the default model binder will of course not be able to convert an empty strong to an integer and automatically add an error to the ModelState. Then the controller actin is invoked and all you do is to reset the values of this trip object but of course the error that was added to ModelState is left and that's what you observe.
So the solution to this problem would be to write a custom model binder or make those properties nullable integers:
public int? CarCount { get; set; }
public int? BusCount { get; set; }
public int? TruckCount { get; set; }
and then have your action look like this:
public ActionResult Create(Trip trip)
{
if (!ModelState.IsValid)
{
// there were errors => redisplay the view
return View(trip);
}
// at this stage the model is valid => process it
...
}

Entity Framework 4.1 Automatic date

i'm quite new to Entity Framework (and asp.net mvc 3) and this is my really first experience with EF4.1 code first.
My question is simple: when I generate via model a new table for database I would like to make
Automatically add current datetime to a field when a new row is created.
Automatically update the field every time the field is updated.
Actually, the variable appears like:
[DisplayName("Data Modifica")]
[DataType(DataType.DateTime)]
[DisplayFormat(DataFormatString = "{0:d}")]
public DateTime DataModifica { get; set; }
I guess i could write something on "OnModelCreating" event of datacontext but I'm too new to already master this :)
Can someone help?
thanks in advance,
V.
That has nothing to do with creation of model. The "model" is description of your mapping between classes and database. OnModelCreating is used to modify mapping definition, not to modify data. It has nothing to do with data in the entity instance itself.
If you want automatic modification you can override SaveChanges:
public override int SaveChanges()
{
DateTime now = DateTime.Now;
foreach (var entity in ChangeTracker.Entries<YourEntityType>()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified)
.Select(e => e.Entity))
{
entity.DateModifica = now; // set the date
}
return base.SaveChanges();
}
Why not define the property to be one with a backing field, which is initialized to the default value ?
private DateTime _dateOfRequest = DateTime.Today;
[Display(Name = "Date of Request"), DataType(DataType.Date)]
public System.DateTime DateOfRequest {
get { return _dateOfRequest; }
set { _dateOfRequest = value; }
}

Resources