in MVC 3 i have a EF code first class like this:
public class Client
{
[Key]
[MaxLength(4)]
[Display(Name="labClientID", ResourceType=typeof(Resources.Translations.Client))]
public string ClientID { get; set; }
[MaxLength(50)]
[Display(Name="labName", ResourceType=typeof(Resources.Translations.Client))]
public string Name { get; set;}
}
Client is used eg in following Person class:
public class Person
{
[Key]
[MaxLength(50)]
public string UserID { get; set; }
[MaxLength(50)]
public string LastName { get; set; }
[UIHint("ForeignKey")]
[MaxLength(4)]
public string ClientID { get; set; }
public virtual Client Client { get; set; }
}
Clients have IDs like 01,02,03 etc
In an edit view I have the following razor statement for the edit person view:
#Html.DropDownListFor(m => m.ClientID , new SelectList(ViewBag.Clients, "ClientID", "Name"))
The ViewBag.Clients is build up before with:
ViewBag.Clients = (from x in Context.Client select new {x.ClientID, x.Name});
Now comes the strange part: Indepented which value I choose for the ClientID in the person class, the DropDownList always displays the second entry from the client table when I open the edit view that contains the DropDownListFor statement.
I debugged the clients viewbag and it contains the correct values, also I used a editorfor instead of an DropDownListFor and the clientid in the person entity has the correct value.
Have you an idea where the problem is?
Related
I am developing an ASP.Net Core Web API using EF Core Code First (C#) and SQL Server.
I have a fairly simple scenario which I just cannot figure out. I have a Form entity and a Site entity. Each Form can have many Sites and each Site can be in many Forms. To enable this I have a SiteForm joining table. For each Site associated with a Form there is a Leaving Date field. So my SiteForm class looks like this:
public class SiteForm
{
public Guid SiteId { get; set; }
public Site Site{ get; set; }
public Guid FormId { get; set; }
public Form Form{ get; set; }
public DateTime? LeavingDate { get; set; }
}
My Form's Data Transfer Object (FormDto) is as follows:
public class FormDto
{
public Guid Id { get; set; }
...
public ICollection<LinkedSiteDto> LinkedSites { get; set; }
= new List<LinkedSiteDto>();
}
And my LinkedSiteDto is like this:
public class LinkedSiteDto
{
public Guid Id { get; set; }
public string Name { get; set; }
public string Ident { get; set; }
public DateTime? LeavingDate { get; set; }
}
Having populated the database I can get the Sites for each Form using the following mapping:
CreateMap<Form, FormDto>()
.ForMember(dto => dto.LinkedSites, opt => opt.MapFrom(
form => form.SiteForms.Select(sf => sf.Site).ToList()));
I just cannot figure out how I would include the LeavingDate value from each joining table entry? Any suggestions would be very gratefully received.
My query involves multiple tables and from what I've read on Dapper, I can only find examples, that I understand at least, that query one model.
Below are my 3 classes under the Models folder:
public class User
{
public string UserName { get; set; }
public string UserId { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
}
public class Date
{
public string UserName { get; set; }
public string UserCode { get; set; }
public string LastLogin { get; set; }
}
public class Photo
{
public class UserName { get; set; }
public string UserId { get; set; }
public string PhotoUrl { get; set; }
}
In my repository I have my connection code and then a method to get all the information I need, however this method is tied to the User model only but I also need to retrieve the photo and when I try to make a compound class so I can the User and Photo models in the view, it gives me an error saying it expects only the User DataView.
public List<User> GetAll()
{
using (SqlConnection cn = new SqlConnection(connectionString))
{
var allResults = cn.Query<User>("SELECT UserName, Email, Phone, (SELECT TOP 1 PhotoPath FROM Photo WHERE User.UserId = Photo.UserId) FROM User)
Your User class does not contain property like PhotoPath - where you expect Dapper put will new/additional value to?
You should create new class (ViewModels/UserAndPhoto.cs for example), which contains all properties you are selecting - then Dapper will read it from database successfully.
I've just started using AutoMapper in an MVC ASP.NET project to map my domain models to my view models. eg.
public class PersonModel
{
public string FirstName { get; set; }
public string NickName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
}
public class PersonViewModel
{
public string FirstName { get; set; }
public string NickName { get; set; }
public string LastName { get; set; }
public DateTime BirthDate { get; set; }
}
// Somewhere...
Mapper.CreateMap<PersonModel, PersonViewModel>();
Mapper.CreateMap<PersonViewModel, PersonModel>();
Having adopted this pattern, I'm concerned the following scenario happening in future:
1) Developer A creates Person View which shows editors for all 4x properties
2) Developer B later removes "Nickname" editor from the Person View, but leaves in PersonViewModel
3) Because the Nickname value is never preserved in the View, hence submitted on Save, Automapper starts mapping a null value for "Nickname" from PersonViewModel -> PersonModel and overwriting data without any run-time or compile-time warning.
Is this a legitimate risk, have you run into it, and how did you deal with it?
You can mitigate against such risks by having server side validation and automated end to end testing.
So in your example one of the tests would be that 'when saving a person the nickname should contain a value'.
I have a database first model, where is a Person entity, like this:
public partial class Person
{
public System.Guid personID { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string sex { get; set; } // since in the DB it is char(1), default = 'F'
}
I defined a public enum for sex selection:
public enum Sex
{M, F}
which I want to use it to select the sex of the person and to render it as a radio button group.
I followed this solution: pass enum to html.radiobuttonfor MVC3 but couldn't make it work.
According to that answer, I added the RadioButtonForEnum extension, I extended my partial class with another property, like this:
public partial class Person
{
public System.Guid personID { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string sex { get; set; } // since in the DB it is char(1), default = 'F'
public Sex personSex { get; set; }
}
and changed my viewmodel and controller to use the enum.
Now I got the error:
The associated metadata type for type 'MyApp.Models.Person' contains the following unknown properties or fields: personSex. Please make sure that the names of these members match the names of the properties on the main type.
How can I fix this, since the model is derived from the database?
I have this model:
namespace easyBooking.Models
{
public class CardInfo
{
public string name { get; set; }
public string adress { get; set; }
public string zipcode { get; set; }
public string city { get; set; }
public string ccsID { get; set; }
public string birthday { get; set; }
public string nationalitet { get; set; }
public string cardType { get; set; }
}
}
which I populate from a function and return to the controller. The problem is that I cannot hand this model to my view, since it does not implement IEnumerable... Instead I have to add information to the viewBag like this:
var cardInfo = FunctionLib.cardCampingPas(myArray);
ViewData.Add("name", cardInfo.name);
ViewData.Add("adress", cardInfo.adress);
ViewData.Add("nationalitet", cardInfo.nationalitet);
ViewData.Add("ccsID", cardInfo.ccsID);
ViewData.Add("zipcode", cardInfo.zipcode);
ViewData.Add("city", cardInfo.city);
ViewData.Add("cardType", cardInfo.cardType);
return View("../Reservation/New", ViewData);
which is kind of stupid, when I should be able to just add the cardInfo model directly to the View.
var cardInfo = FunctionLib.cardCampingPas(myArray);
return View("../Reservation/New", cardInfo);
So basically I just need to pass a bunch of strings to the view. How can my model CardInfo be accessed directly from my view?
Update
#rene - view data where I added a #model declaration. I did get some errors when I tried it last, but it must have been because I tried to foreach it or something.. now... just no error, and I have no idea if anything is passed to the view or how to get the data.
#model easyBooking.Models.CardInfo
#{
ViewBag.Title = "New";
}
<h2>Ny reservation</h2>
<p>Benyttet kort: #Model.cardType</p>
This now works...
You can pass your collection directly to the view.
In the view, you'll need to declare the model type:
#model IEnumerable<CardInfo>