Navigating ID properties to source with an OData API - asp.net-web-api

I have a class which is exposed by an ASP.NET OData V4 API:
public class Person
{
public int TitleId { get; set; }
//Other properties like First Name, Last Name, DoB and so on...
}
The TitleId property is an Id that maps to a persons Title (Mr, Miss, Mrs so on) which is located at a different OData endpoint address.
Is there any way of providing metadata to let the consumer of the API know where the lookup values are for this property or should I approach this in a different way?
Edit: I am looking for a way to provide metadata to inform the consumer of the location of the lookup values. There is no database involved, this is a mapping layer over a much more complicated API.

if you have the Class of Title and have that in the Database this is working:
public class Title
{
public int Id { get; set; }
public string TitleName { get; set; }
}
then use this that as Virtual in your current model.
[ForeignKey("TitleId")]
public virtual Title { get; set; }
public int TitleId{ get; set; }
I'm sure it does the mapping.
then just address them to Title.TitleName.

Related

Add calculated value to OData result

I'm trying to add some info to the data result whether the user has read or write access to the entity.
Lets assume I have this entity:
public class Foo
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Access> AccessRights { get; set; }
}
Where AccessRights holds the user id and if they have read/write access.
Currently I just $expand AccessRights and calculate if the user has read/write access in the frontend. However I'd like this calculated property to be added to the result.
Example json result:
{
id: 1,
name: "foo",
hasReadAccess: true,
hasWriteAccess: true
}
Is it possible to do this? Keep in mind that HasRead/WriteAccess doesn't exist on the model nor should it.
You need to split your model in two: a data access model (what you get from the data access layer) and a data transfer model (what you send as a response).
Assuming your current Foo class as the data access model, you simply need to define another class FooResponse (or whatever name suits you) as follows.
public class FooResponse
{
public int Id { get; set; }
public string Name { get; set; }
public bool HasReadAccess { get; set; }
public bool HasWriteAccess { get; set; }
}
Then define a transformation function that maps from Foo instances to FooResponse instances. AutoMapper is a good tool for the job.

"[Required]" Data Annotation Not Enforced on POST Methods

I had the idea to use Data Annotations in order to validate ModelState. This works wonderfully. The problem I am having is that the [Required] Data Annotation is being enforced on [Key] fields on post. Our data layer takes care of setting Id's and we don't want anyone consuming the service to have to worry about Id's. Is there a way around this in WebApi2?
I have looked at this question, and removing the Id field from ModelState in the POST method before checking for valid ModelState would work. The issue with that is that we use a filter for ModelState.
EDIT:
After doing some more research, what I am essentially wanting to do is what the [Bind] attribute does in MVC. After some research, it does not look like this is a feature that has yet been implemented in WebApi. If anyone has any ideas, feel free to post them.
What you can do is to replace your entity with a data transfer object, which is identical to your original entity without the ID field. For example,
The original entity may look like this
public class User
{
[Required]
public Guid UserId { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Username { get; set; }
public string Email { get; set; }
}
and the DTO may look like this
public class UserDto
{
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Username { get; set; }
public string Email { get; set; }
}
Hope this helps.

Multilingual MVC 4 best practice

I know if I want to create a multilingual MVC4 application I would use resource files according to CultureInfo, but that would be useful for application's labels, messages, titles..etc, however I was thinking about defining a list of counties' names and their cities in many languages, now should I define them in a resource files (which can be exhausting) or should I use a table with many columns for each language?
And if I used resource files, how can I tell which country a user is from when he register in the system?
Which one is best practice? Is there any other approach?
Using multiple columns for each language will work, but it will also get out of hand pretty quickly as more columns and languages need to be added down the road. So I'd advise against that approach.
What you can do however is move the columns that need to be localized to a different table with a compound primary key. Here's a simple example with a cities table :
You'll have classes that look somewhat like this :
// City.cs
public class City
{
public int CityId { get; set; }
public string UnlocalizedField1 { get; set; }
public string UnlocalizedField2 { get; set; }
// Optional
public virtual List<CityTranslation> Translations { get; set; }
}
// CityTranslation.cs
public class CityTranslation
{
public int CityId { get; set; }
public string LanguageId { get; set; }
public string LocalizedField1 { get; set; }
public string LocalizedField2 { get; set; }
}
Then it becomes rather trivial to query your data in the language you need.

How to access an association in view from one POCO with several references to another

Sorry about the title; couldn't think of a better one.
Any way, I'm accessing an associated property in my view like so:
#Model.Company.CompanyName // No problems here...
The model is a viewmodel mapped to an EF POCO. The Model has several properties associated to the Company table. Only one of the properties in the model share the same name as the PK in the Company table. All the other properties reference the same table:
public class MyModelClass
{
public int Id { get; set; }
public int CompanyId { get; set; }
public int AnotherCompanyId { get; set; } // References CompanyId
public int AndAnotherCompanyId { get; set; } // References CompanyId
public Company Company { get; set; }
}
public class Company
{
public int CompanyId { get; set; }
public string CompanyName { get; set; }
public string Address { get; set; }
}
I'm obviously missing something here.
How can I get the names of the other companies in my Model?
Any help is greatly appreciated.
The model is a viewmodel mapped to an EF POCO
I think you are confusing the notion of a view model. A view model is a class that is specifically designed to meet the requirements of your view. So if in your view you need to display the company name and not the company id then your view model should directly contain a CompanyName property. Or a reference to another view model (CompanyViewModel) which contains the name directly. It is then the responsibility of your controller action to query your domain models (EF entities) and aggregate them into a single view model tat will contain all the necessary information that the view requires.
Here's how a typical view model might look like:
public class MyViewModel
{
public CompanyViewModel Company { get; set; }
public CompanyViewModel AnotherCompany { get; set; }
public CompanyViewModel AndAnotherCompany { get; set; }
}
public class CompanyViewModel
{
public string Name { get; set; }
}
Where the data comes from in this view model is not important. You could have the Company property populated from your EF stuff, the AnotherCompany property populated from a XML file and AndAnotherCompany from WCF.

MVC3: Attribute for not mapping a property to a DB column

I’m using ASP.NET MVC3. I have a model that has one property that I don’t want to store in the database. Is there an attribute that I can put on the property to achieve this? Thanks.
public class Person
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
[NotMapped]
public string FullName { get; set; }
}
The attribute are in the namespace System.ComponentModel.DataAnnotations
Just to add more options... this is why I prefer to keep my domain model separate from my view model. My view model often has additional fields necessary for rendering the view which does not belong in the domain model. The design I typically use is described pretty well here.

Resources