DataAnnotation Name class to be serialised - data-annotations

Is it possible to name the class/ViewModel for a WebAPI response object using System.ComponentModel.DataAnnotations or is there an alternative;
//[DataMember(Name="CarDepot")] -- this doesn't work
//[Display(Name = "CarDepot")] -- this doesn't work
public partial class CarDepotVM
{
[Display(Name = "CarDepotVM")]
[DataMember(Order = 0)]
[Required]
public Car[] Cars { get; set; }
}
The library which contains the following code is PCL complaint, therefore I cannot use any external libraries which aren't compatible.

Related

Key data annotation not working when assigned to a separate partial class in my razor web app using efcore .netcore

I am developing an application in razor web apps (asp.netcore) and scaffolding db tables using efcore.
I performed a db-scaffold on my OnlineForms data table, which created my OnlineForms.cs Class. When i directly put the [key] attribute on top of the formid property in this class, I can save to the data table without any issues.
But when I move the [key] data annotation into the partial class OnlineFormsValidation, which references OnlineForms, through the [ModelMetadataType] attribute, and I try to save data; I get the error: "The entity type 'OnlineForm' requires a primary key to be defined."
The Required annotations work properly from inside OnlineFormsValidation class, but the [Key] annotation does not.
Thank you in advance. Any help would be greatly appreciated.
OnlineForm.cs:
namespace VehicleTakeHomeApp.Data.Models
{
public partial class OnlineForm {
[Key] <== works if i put it here, but I want to move it to OnlineFormValidation.cs
public int FormId { get; set; }
public string EmployeeId { get; set; }
public string Name { get; set; }
}
}
OnlineFormValidation.cs:
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
namespace VehicleTakeHomeApp.Data.Models
{
[ModelMetadataType(typeof(OnlineFormValidation))]
public partial class OnlineForm
{
}
public class OnlineFormValidation
{
[Key] <== this annotation is not getting picked up, even though the Required annotations below it get picked up.
public int FormId { get; set; }
[Required(ErrorMessage = "Employee ID is required.")]
public string EmployeeId { get; set; }
[Required(ErrorMessage = "Name is required.")]
public string Name { get; set; }
}
}
I had the OnModelCreating method in my dbcontext class commented out. This method contains the HasKey() from the initial db-scaffold.
I uncommented the OnModelCreating method, and now I don't need to add the [Key] annotation, to either class and it works.
It's more of a workaround then a solution, but its works.

Creating dropdownlist in ASP.NET MVC3 using Razor view engine

I am creating a User Registration form in ASP.NET MVC3 using razor view engine. I am facing problem to create a dropdownlist for country. Country list come from xml file.
My project hierarchy is as follows
BusinessLayer -> User_Account -> Account_Registration.cs
This is a class library in which I want to create a Model for user registration. The code for user model is as follows
public class Account_Registration
{
public string User_Name { get; set; }
public string User_EmailID { get; set; }
public string User_Password { get; set; }
public string User_RePassword { get; set; }
public DateTime User_BirthDate { get; set; }
public enum_Gender User_Gender { get; set; }
public string User_Address { get; set; }
public string User_City { get; set; }
public string User_State { get; set; }
public IEnumerable<SelectListItem> User_Country { get; set; }
public string User_WebSite { get; set; }
public string User_Description { get; set; }
}
Now I want to know that where I should put country XML file and how can I create dropdownlist for XML file.
My Xml file is as follows
<countries>
<country code="AF" iso="4">Afghanistan</country>
<country code="AL" iso="8">Albania</country>
<country code="DZ" iso="12">Algeria</country>
</countries>
As I have to deploy this project on IIS so I want to know where should I put xml file so that I can access it in Account_Registration model which is in class library project and how to create dropdownlist for population countries.
Thanks
You probably shouldn't read xml file each time you render registration page. That would be one little bottleneck you'd have since hard drive operations are costly. I'd recommend reading it into memory (like at the application startup once and somewhere into the global variable, e.g. Countries).
For rendering your list, I'd recommend looking at the following article. Basically, it goes like this:
Html.DropDownList(“countries”, new SelectList(model.Countries), “CountryId”, “CountryName”))
you can create own extension for DropDown.
public static class GridExtensions
{
public static MvcHtmlString XmlDropDown(this HtmlHelper helper, string name, string value)
{
var document = XDocument.Parce(value);
var model = new List<SelectListItem>();
foreach(XElement element in document.Elements("countries/country"))
{
model.Add(new SelectListItem(){Text=element.Value, Value=element.Attribute("iso").Value})
}
return Html.DropDownList(name, model))
}
}
So, on view you can use
Html.XmlDropDown(“countries”, model.Countries)

MVC 4, Upshot entities cyclic references

I have a DbDataController which delivers a List of Equipment.
public IQueryable<BettrFit.Models.Equipment> GetEquipment() {
var q= DbContext.EquipmentSet.OrderBy(e => e.Name);
return q;
}
In my scaffolded view everything looks ok.
But the Equipment contains a HashSet member of EquipmentType. I want to show this type in my view and also be able to add data to the EquipmentType collection of Equipment (via a multiselect list).
But if I try to include the "EquipmentType" in my linq query it fails during serialisation.
public IQueryable<BettrFit.Models.Equipment> GetEquipment() {
var q= DbContext.EquipmentSet.Include("EquipmentType").OrderBy(e => e.Name);
return q;
}
"Object Graph for Type EquipmentType Contains Cycles and Cannot be Serialized if Reference Tracking is Disabled"
How can I switch on the "backtracking of references"?
Maybe the problem is that the EquipmentType is back-linking through a HashSet? But I do not .include("EquipmentType.Equipment") in my query. So that should be ok.
How is Upshot generating the model? I only find the EquipmentViewModel.js file but this does not contain any model members.
Here are my model classes:
public class Equipment
{
public Equipment()
{
this.Exercise = new HashSet<Exercise>();
this.EquipmentType = new HashSet<EquipmentType>();
this.UserDetails = new HashSet<UserDetails>();
}
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Picture { get; set; }
public string Link { get; set; }
public string Producer { get; set; }
public string Video { get; set; }
public virtual ICollection<EquipmentType> EquipmentType { get; set; }
public virtual ICollection<UserDetails> UserDetails { get; set; }
}
public class EquipmentType
{
public EquipmentType()
{
this.Equipment = new HashSet<Equipment>();
this.UserDetails = new HashSet<UserDetails>();
}
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public virtual ICollection<Equipment> Equipment { get; set; }
public virtual ICollection<UserDetails> UserDetails { get; set; }
}
try decorating one of the navigation properties with [IgnoreDataMember]
[IgnoreDataMember]
public virtual ICollection<Equipment> Equipment { get; set; }
The model generated by upshot can be found on the page itself. In your Index view you will see the UpshotContext HTML helper being used (given that you are using the latest SPA version), in which the dataSource and model type are specified.
When the page is then rendered in the browser, this helper code is replaced with the actual model definition. To see that, view the source code of your page in the browser and search for a <script> tag that starts with upshot.dataSources = upshot.dataSources || {};
Check here for more info about how upshot generates the client side model.
As for the "backtracking of references", I don't know :)
I figured out - partially how to solve the circular reference problem.
I just iterated over my queried collection (with Include() ) and set the backreferences to the parent to NULL. That worked for the serialisation issue which otherwise already breaks on the server.
The only problem now is the update of a data entity - its failing because the arrays of the referenced entitycollection are static...
To solve the cyclic backreference, you can use the IgnoreDataMember attribute. Or you can set the back reference to NULL before returning the data from the DbDataController
I posted a working solution to your problem in a different question, but using Entity Framework Code First.
https://stackoverflow.com/a/10010695/1226140
Here I show how to generate your client-side model manually, allowing to you to map the data however you please

How should be my DTO object for ASP.Net MVC View?

i'd like to know, I have a application in asp.net mvc and nhibernate. I've read about that in the Views on asp.net mvc, shouldn't know about the Domain, and it need use a DTO object. So, I'm trying to do this, I found the AutoMapper component and I don't know the correct way to do my DTOS, for some domain objects. I have a domain class like this:
public class Entity
{
public virtual int Id { get; set; }
public virtual bool Active { get; set; }
}
public class Category : Entity
{
public virtual string Name { get; set; }
public virtual IList<Product> Products { get; set; }
public Category() { }
}
public class Product : Entity
{
public virtual string Name { get; set; }
public virtual string Details { get; set; }
public virtual decimal Prince { get; set; }
public virtual int Stock { get; set; }
public virtual Category Category { get; set; }
public virtual Supplier Supplier { get; set; }
public Product() { }
}
public class Supplier : Entity
{
public virtual string Name { get; set; }
public virtual IList<Product> Products { get; set; }
public Supplier() { }
}
I'd like to get some example of how can I do my DTOs to View ? Need I use only strings in DTO ? And my controllers, it should get a domain object or a DTO and transform it on a domain to save in repository ?
Thanks a lot!
Cheers
There is no guidelines on this matter and it depends on your personal chice. I have few advices that have proven useful in practice:
1. Use flat DTOs - this means that the properties of the DTO must be as primitive as possible. This saves you the need for null reference checking.
For example if you have a domain object like this:
public class Employee
{
prop string FirstName{get; set;}
prop string LastName{get; set;}
prop Employee Boss{get; set;}
...
}
And you need to output in a grid a list of employees and display information for their 1st level boss I prefer to create a DTO
public class EmployeeDTO
{
prop string FirstName{get; set;}
prop string LastName{get; set;}
prop bool HaveABoss{get;set}
prop string BossFirstName{get; set;}
prop string BossLastName{get; set;}
...
}
or something like this (-:
2. Do not convert everything to sting - this will bind the DTO to a concrete view because you'll apply special formatting. It's not a problem to apply simple formatting directly in the view.
3. Use DTOs in your post actions and than convert them to domain objects. Usually controller's actions are the first line of deffence against incorrect data and you cannot expect to be able to allways construct a valid domain object out of the user's input. In most cases you have to do some post-processing like validation, setting default values and so on. After that you can create your DTOs.

In MVC 2, how to annotate a class for an UI Helper Template (not a property)?

I know this works for single properties as per Scott Guthrie's blog to auto-magically use a partial view to render a partial model passed to it (UI Helper like in dynamic data):
[UIHint("StateDropDown")]
public string State { get; set;}
But how do you annotate an entire class to use an UI helper like this:
[UIHint("Address")]
public class Address {
public string addr1 { get; set; }
public string addr2 { get; set; }
public string city { get; set; }
[UIHint("StateDropDown")]
public string state { get; set; }
public string zip { get; set; }
}
(Except [UIHint("Address")] doesn't seem to work on classes. I see in his examples, he has "Customer.aspx" in the Shared->EditorTemplates folder, so I assume this is possible.
Make a template with the name of the class, and it just works.

Resources