Expose ApplicationUser in WebAPI - c#

I would like to be able to expose a list of users using WebAPI 2. However since I am using the new Asp.Net Authentication framework in MVC5, I can't seem to find a way to only mark specific fields as DataMembers.
Heres what I have:
[DataContract]
public class ApplicationUser : IdentityUser {
public Nullable<DateTime> birthday { get; set; }
[DataMember]
public int tolerance { get; set; }
[DataMember]
public string twitter { get; set; }
}
However, that doesn't seem to work because IdentityUser doesn't have the [DataContract] attribute. I've tried creating a custom IdentityUser, but I haven't been able to build after creating a custom copy of IdentityUser.
Any tips or work arounds here? I'd prefer not to have to create a ViewModel, unless that's the current best practice.

I know this is an old question and I stumbled upon it when I was trying to achieve the same thing. Here's what I ended up doing. You could override your properties and mark them as [JsonIgnore] so that they won't get serialised automatically.
public class ApplicationUser : IdentityUser
{
public UserType UserType { get; set; }
[JsonIgnore]
public override string PasswordHash
{
get { return base.PasswordHash; }
set { base.PasswordHash = value; }
}
}

You probably should just send a different object with the user info you need as opposed to serializing the user object.

What formatter do you want to use? I don't see any issue with default Json formatter. But for xml serializer, it requires base class to be DataContract as well.
View model is always the best practice here, although most of the samples for web api are using data entity for simplicity. The two models are separate of concerns. View model represents the contract of your api and the data model represents your domain concept. Combining two models into one can impact your design decision or even more seriously, can cause security issues. Using data entity may expose unexpected data to user. For example, different formatters have different rules to control the exposure of model. JsonIgnore doesn't work in xml formatter. It will be more complicated if you have custom formatter. Especially for the identity user entity, which has many sensitive properties like pasword hash, security stamp. I won't recommend you expose it to public.
BTW, there is many mapper tools that can help to simplify the mapping from domain model to view model. You may need them: http://www.nuget.org/packages?q=mapper

Related

Proper use of DataAnnotations in a ASP.NET MVC app with Domain classes in a separate project?

I have an N tier app in which Data, Domain and the front-end layers are in separate projects. I am using ASP.NET MVC to create the website and I am trying to add validation rules by using System.ComponentModel.DataAnnotations. Currently I have done it on the domain classes' properties.
I would like to know whether it is a good practice to apply the validation rules directly to the Domain classes? Or it is better to create ViewModels classes in the ASP.NET app and apply the validation rules to the properties of the ViewModel classes?
Hope this question fits here
I appreciate any help.
ViewModel is much better, because ViewModel should understand if it gets valid input from the user. And then you can fix all other exception during convertion using AutoMapper. I would also create a lot of custom , DataAnnotations, DataTypes, Editors, ModeMetaDataRules, and ModelBinder to go with app.
Here is parts of code for ModelFilter using custom ModelBuilder, I am going post part of it, because there is a lot of code involved, but it should get you on right track.
public interface IModelMetadataFilter
{
void TransformMetadata(ModelMetadata metadata,
IEnumerable<Attribute> attributes);
}
public class MultilineTextByNameConvention : IModelMetadataFilter
{
public void TransformMetadata(ModelMetadata metadata, IEnumerable<Attribute> attributes)
{
if ( !string.IsNullOrEmpty(metadata.PropertyName) &&
string.IsNullOrEmpty(metadata.DataTypeName) )
{
if ( metadata.PropertyName.ToLower().Contains("notes")
|| metadata.PropertyName.ToLower().Contains("description")
|| metadata.PropertyName.ToLower().Contains("comment")
)
{
metadata.DataTypeName = DataType.MultilineText.ToString();
}
}
}
}
This code looks for every ViewModel that has property name containing words 'notes', 'description', and 'comment', automatically applying Multitext DataType attribute for all that properties. This type of code can be used for a lot of other different situations. For example fields like SSN can have particular format using RexExpr DataAnnotation, and so on...
You can set attributes on partial classes of your entities and your auto generated classes will not get overridden.
For instance,
Let's say you have entity TheEntity
In a separate file with the Same namespace you can write:
namespace SameNamespaceAsEntities
{
internal sealed class TheEntityMetadata
{
//AStringInTheEntity appears twice in your project
//once in the auto gen file, and once here
[Required(ErrorMessage = "Field is required.")]
public string AStringInTheEntity{ get; set; }
}
//http://stackoverflow.com/questions/14059455/adding-validation-attributes-with-an-entity-framework-data-model
[System.ComponentModel.DataAnnotations.MetadataType(typeof(TheEntityMetadata))]
public partial class TheEntity : IEntity //you can set contracts
{

Hiding/Showing properties and ordering properties in MVC

I am about to upgrade our software from ASP.NET WebForms to .NET MVC. All over the web it shows how to create a view based on a model, which is fine.
In this project the users can hide properties of the model to generate a view suitable for them, yet another client in another website and hide other properties.
The code is all the same, but i would like to know if there is a way to hide/show properties of a model based on a condition easily, hopefully without having a lot of IF statements all over my views.
Example - How can 1 client see only name and town, yet another client see all 3 properties. Just need to show based on a condition.
public class MyObject() {
public property name { get; set; };
public property town { get; set; };
public property customText { get; set; }
public MyObject() {}
}
NOTE: Users can also determine the order of these properties, can i do that as well easily ?
Just to say that creating separate views is not possible. The above is a very simple example of a model with properties. Our models can have about 100 properties, and the user can turn these on and off whenever they like, so it needs to be able to be done dynamically
Is there a way of creating a ViewModel on the fly?
Thanks in advance
Create a Property class or similar and model you data appropriately:
public class Property
{
public string Name {get;set;}
public bool Visible {get;set;}
public int Order {get;set;}
}
Then your view model can be similar to your example:
public class ViewModel
{
public Property Name {get;set;}
public Property Town {get;set;}
public Property CustomText {get;set;}
}
Well you cannot bind multiple models to your view.Obviously you have to do workaround in your view based on user roles.
Or else create a seperate model and view for each user roles.
I have been working on a project called Dynamic MVC.
http://dynamicmvc.com
It currently does not do what your asking. The functionality is already there, it is just not exposed the way you need it. However, if you are interested I will add the functionality so you can pass the properties you want to display in the querystring. Eventually, a customizable dynamic view will generate your page for you without any coding required. Also, the order of the properties would determine the order on your page. This would work for any model with the DynamicEntity attribute.
Let me know if your interested and I can include it in the next release.

Returning Domain Objects From Web Service

This may be a philosophical question, but I thought I'd ask it here since I'm suffering from a bit of analysis paralysis.
I'm currently working on a browser based game (Client-side HTML/Javascript, and WCF Web Services to reach the backend) and I'm trying very hard to have a nice, rich Domain Model.
So here's my question. I have a class called Squadron
public class Squadron
{
public string SquadName { get; set; }
public User Owner { get; set; }
public int XPosition { get; set; }
public int YPosition { get; set; }
public int XTarget { get; set; }
public int YTarget { get; set; }
}
The Squadron is owned by a User
public class User
{
public string Username { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public int UserID { get; set; }
public List<string> Roles { get; set; }
}
I also have a Squadron repository that returns a fully populated Squadron object, based on it's ID. I have a webservice (basically, GetSquadron) that should return the Squadron. However, the attached User object has some information that I probably don't want exposed to any client (Password, as an obvious example). Although it seems that Password should be a part of this Domain object...it doesn't seem like something I always want populated.
I've considered adding another layer of logic (after the Domain object has been populated) that will ensure that the calling user has access to certain fields, but I was wondering what best practices I can find in the community. I tried Googling but I haven't had much luck.
Thanks!
EDIT: Before anyone harps on it, the password is hashed. I never store a clear-text password in the database. I just figured that I probably shouldn't be returning the password, encrypted or not.
EDIT 2 (Phillip): I've populated the User object because I do need a couple of those fields down in the client side (Username and UserID, and possibly Email). Maybe creating some DTO's is the answer to the problem. I guess I thought it'd be nice to have a common model across all layers.
I would consider substituting the Owner (User) property for the UserID property. I don't see any real reason that you would need the entire User object in Squadron. However, I don't know your design or intent well. It is also a very bad practice to pass around a user password even if it's encrypted.
If you do need the Person details in the Squadron object I'd suggest creating a new Person view model that does not include the user Password.
I agree with PhillipPDX about not passing around the password, but I would be hesitant to use DTOs to pass data from a web service.
If I'm understanding that tech right, you would create the DTO, serialize the object which is then returned by the web service. Typical object serialization tends to carry a lot of overhead and results in larger amounts of data being returned from the service, and an object that requires .Net on the client side to deseralize the data back into an object (DTO).
A more modern approach would be to use something like NewtonSoft's JSON Serializer to convert the POCO (Plain Ol' C# Object) into a JSON string which is then returned by the web service. Since your game is browser / Javascript based JSON would be a natural fit for this use case.

How to show ApiMember attribute data for properties of complex types on ServiceStack's generated metadata page

Is it possible to have ApiMember attribute data show up on ServiceStack generated metadata for properties of complex types on the request DTO? If so, how can this be achieved?
Let's say I have a request DTO with the following properties:
public Customer Customer { get; set; }
public List<CustomerOrder> CustomerOrders { get; set; }
and a customer type with the following properties:
public string Id { get; set; }
public string CompanyName { get; set; }
public string ContactName { get; set; }
I would like to be able to add the ApiMember attribute to the customer's properties. However, when I do so, the metadata page for the request DTO does not show the customer's properties.
I would also like the CustomerOrder's properties to be shown on the metadata page as well. I realize this could be a little trickier due to it being a list of the CustomerOrder type.
If this is not supported, recommendations for other options are welcome.
I don't think what you're looking for is supported at the moment. I think the Api and ApiMember attributes are meant to follow/mirror the Swagger API and DataTypes. In the Swagger API there is support for complex types but in order get the details of a complex type it needs to be in the models section of the API declaration. I don't think models is currently handled within ServiceStack. At least, I haven't stumbled across it within the code

Decorate model fields with metadata from resource file

I would like to separate my attribute decoration(3-4 per field) by having them someplace else so that my code looks readable.
Also the arguments passed to some attributes should come from a resource file.
EG:[Required("Cannot proceed without entering *field_Name*")]
I need just [Required]
Possible duplicate of this question(on which i couldn't resist offering a bounty) : Default resource for data annotations.
To answer your first question, you can use buddy classes. For example, if you have a "User" model, then you can create a "UserMetadata" buddy class. You can then add attributes to properties in the buddy class instead of the main class. ASP.NET MVC fully supports this, and will use your buddy class for things like validation and display name. Here is how you declare a buddy class:
[MetadataType(typeof(UserMetadata))]
public class User
{
public string Name { get; set; }
}
public class UserMetadata
{
[Required]
public object Name { get; set; }
}
Note that the property type in the buddy class can always be "object", because MVC doesn't look at the property type in buddy classes.
Note also that MetadataTypeAttribute can be found in the System.ComponentModel.DataAnnotations namespace.
For your second question, you can look at the answer that I posted here:
Default resource for data annotations in ASP.NET MVC
For the first question, maybe you could try using Fluent Validation. You can hook it up to MVC by following these instructions.
For the second question, I've posted an answer here: Default resource for data annotations in ASP.NET MVC

Categories