Object property validation in MVC (using web service) - asp.net

I have an ASP.Net MVC site, which connects to a web service.
The site's view model contains objects for each group of required service data AccountDetails (containing AccountId, AccountType, etc.), ContactDetails (containing Name, Address, etc.) and so on.
The service has a 'CreateUser()' method that accepts these objects as parameters, and it then performs all the validation itself - handing back an Object which has an array of any errors that have been found, including the name of the specific property/field.
I would like to know if there is a way of passing this returned error data into either DataAnnotations or something else.
I specifically can't write the conditions in the model itself, because the validation conditions within the web service are open to change at any moment - and we want this to dictate what fails and what succeeds.
== FURTHER INFO FOR MAKE IT A BIT CLEARER ==
Imagine I were locally (within the View Model) creating the ContactDetails class, I could very simply do this
public class ContactDetails
{
[IsRequired()]
[CustomAttributeofSomekind]
public string FirstName { get; set; }
public string LastName { get; set; }
}
However in this scenario - if we wanted to change the validation critera for whatever reason we would have to change it in both the web service AND in all the client websites that access the service.
We don't want to have to do this - instead I if (in the above) scenario ContactDetails.LastName is suddenly required and must be no more than 10 characters - this should only need updating in the web service.

I think you have two options:
Create a User class to wrap the CreateUser() method and add the DataAnnotations to that (this is what I would do, it allows you to go strongly-typed.)
Call the CreateUser() method directly from the controller Action and use server-side validation. Add each validation error in the CreateUser() result to the ModelState.Errors collection when any validation rules are violated.

Related

Authorize API Controller Methods Based On Route

I'm looking for a way to conditionally enforce the [Authorize] attribute on API Controller methods based on the route they are accessed from.
In my software, I have pages that can be accessed one of two ways, as an authorised user with full access or as an anonymous user in "viewer mode", with limited functionality.
Both of these require access to the same API methods. I want to keep the "full" version of these calls as secure as possible, while the anonymous versions should be unimpeded. To give you an example of such a method before the "viewer mode" existed:
[Route("{outerId:int}/{innerId:int}/Action")]
public virtual HttpResponseMessage PutAction(int outerId, int innerId)
{
...
}
The outerId and innerId are essentially indicators of subdirectories containing the relevant data. I should also point out that the controller has the [Authorize] attribute.
Viewers access deep copies of this data through a different path that only requires one parameter, so my current solution is to anonymise the method and have 2 routes to differentiate the two different access types, authenticating within the method where appropriate:
[AllowAnonymous]
[Route("{id:int}/{innerId:int}/Action", Order = 1)]
[Route("{id:int}/Viewer/Action", Order = 2)]
public virtual HttpResponseMessage PutAction(int id, int? innerId = null)
{
if (innerId != null) // check userId using User.Identity.GetUserId()
...
}
This works well most of the time, but unfortunately these methods will occasionally fail when accessed by full users, as User == null. The Authorize attribute is the only thing I know that would prevent this from happening, but is there a way to only enforce this attribute for different routes?

ASP.NET MVC - How to handle a string in a model that does not allow nulls?

So I'm a bit new to ASP.NET and MVC. I've got an ASP.NET MVC5 application, using Entity Framework 6. I've generated my models from a SQL Server database, and am so far just using the vanilla index/create/details/edit constructs.
In my models, various fields are marked as "Allow Nulls" and others aren't. While creating a new entry, any type that is, say, an int that is left as null is handled nicely by the ModelState.IsValid check and the #Html.ValidationMessageFor messages.
On one entry test, however, I received a DbEntityValidationException. I used the try/catch from this question to find out that it was one of the string (VARCHAR) fields that was left blank.
I am assuming this is because the string class allows nulls, where as int does not (unless declared as Nullable<type> in the model) thus the controller/model doesn't flag it as invalid.
What would be the easiest way to handle this? Is there a way to decorate the string property in the model so it gets checked as well? Or do I need to go as far as attempting to save, catching the exception, and manually handling the validation messages?
Thanks
It is possible to decorate your property with a Required-attribute. Mvc wil show an error message when the user is posting a form while this property is empty.
public class TestClassModel
{
[Required]
public string RequiredString { get; set; }
}

asp.net MVC 4 with Data Access Layer using Entity Framework 5?

In my project, i have first created my Data Access Layer using Entity Framework with the following projects in a single solution,
1.Domain Model - Entity Model (.edmx)
2.Services - Business Services, Dtos, Infrastructure(Configurator), Interfaces and Models(Repository)
Now the problem is, i want to connect this data access layer to my MVC project, i do not know how to make the data access layer projects to behave as the models for my mvc project. So can anyone tell me how to connect my data access layer into my controllers and views.. any references is appreciated. Thanks in Advance !
I think what you're asking is what's the best way for controllers to interact with your services and data layer?
One option is to use the mediator pattern, and decouple the services from the controllers.
There's a great implementation for ASP.NET MVC apps: ShortBus, also available on nuget that I've used in a number of projects, and so far it's worked great.
One of the nice things about ShortBus is it's support for dependency injection. In the example below, all the services are created with Ninject, and require the appropriate registration.
The basic idea is you define queries and commands that the controllers will use, and then add handlers to perform the actual work.
public class AddUser : ICommand<User>
{
public string Email { get; set; }
}
and then a handler:
public class AddUserHandler : ICommandHandler<AddUser, User>
{
private IDatabaseService _database;
private IEmailService _email;
public AddUserHandler(IDatabaseService database, IEmailService email)
{
_database = database;
_email = email;
}
public User Handle(AddUser command)
{
bool created = _database.CreateUser(command.Email);
if (created)
{
_email.SendWelcome(command.Email);
}
}
}
Then inside your controller, all you'd do is issue the command:
public class UsersController : Controller
{
private IMediator _mediator;
public UsersController(IMediator mediator)
{
_mediator = mediator;
}
public ActionResult Create(string email)
{
User user = _mediator.Send(new AddUser("foo#bar.com"));
}
}
The things I like about this pattern are:
Controllers don't need to know how to create a user. It issues a command, and the appropriate business logic handles it.
Each handler can require the services it needs. There's no need to pollute the controllers with services only used by a single action.
It's really easy to unit test. I use a mock, and only need to verify that _mediator.Send() was called with the correct parameters. Then to test the handler, I mock IDatabaseService and IEmailService and verify they are called correctly in the 2 cases.
Commands and queries can be reused, and again, the caller never needs to know what's required to handle the request.
As for the Views, I'd recommend ViewModels.
Each View gets it's own ViewModel, which holds whatever is required for showing that particular page. You'd then map your domain objects to their own individual ViewModels, possibly with AutoMapper.
What's nice about ViewModels is you can format the data appropriately (formatting a DateTime maybe), and then your Views don't need any special logic. If later you decide to update the DateTime format, you only need to change it in one place.
Create a (shared) interface to pass to the layer that's between the DAL and MVC, especially if you're unit testing. Use a repository pattern. Check it out here:
http://csharppulse.blogspot.com/2013/09/learning-mvc-part-5repository-pattern.html
This should get you going...

Best Way to Write an Asp.Net Web Service To Play Well In the Wild

I am writing an API for my ASP.NET application that other developers will use. The API will basically return a list of people with their first name, last name, and id. There are lots of ways to write web services in ASP.NET, the easiest probably being create a web service function (asmx) that returns a DataTable. This is simple enough for other .NET developers to deal with, but I am not convinced that this is the best way to write a web service for general platform and language independence.
What is the currently accepted standard to write a web service like this that plays well in the wild today?
Some ideas that come to mind from experience:
Use WCF, not .asmx. WCF does all the same things that ASMX files do, and is generally the replacement for ASMX services (see here and here).
Write methods using simple POCO data types, like List<Person> rather than DataTable. Basic types serialize more easily and will make more sense in other programming environments since you want your service to be language independent.
Provide generic CRUD methods for managing data. Depending on how your service will be consumed, if the user needs to modify data, a simple method is to provide getBlah(), updateBlah(obj newObj), deleteBlah(obj objToDelete), etc. that use the same data types.
Hide the details that the service consumer doesn't need to know, rather than just blindly exposing all of your data types, structures, and field names as-is. This will make your service more robust for handling internal changes, and you can simplify and control what the end-users see. For instance, if you have a Person class with 30 properties, and only 5 are relevant to the end-user, provide a class that interfaces between Person and a PersonSimple class which is exposed. Without this layer, your end-users will have to modify your code every time you change your data structure, and you will be locked down by this tight coupling.
If security is important
Execute your service over SSL. This protects data transfered over the wire from being sniffed.
Use authentication, either with a Login method and session, or SOAP headers. Services by default are anonymous unless there is some sort of authentication scheme. Even if you think nobody will find your service because you only provide the URL to your users, it will get out somehow, somewhere, and people will try to misuse the service when it does. Plus, you can control who can do what by different logins and authorization schemes.
I am currently working on a similar issue: A web api service in .NET that receives data tables as input parameters, apply some operations on them (using Table Valued Functions), and return some output data tables.
In your case, you don't need to use a complex class like DataTable; you could use an array (List<>) of a simple class with fields like first name, last name and id. Using Web Api of ASP.NET you could do something like the following:
1) Create a new WebApi project in Visual Studio: For example (in VS 2012) C# > Web > ASP.NET MVC 4 Web Application > select "Wep Api" as project template
You will see a VS project with lots of folders, including one named Models
For help see: http://www.asp.net/web-api/overview/getting-started-with-aspnet-web-api/tutorial-your-first-web-api
2) Create a new model code file Person.cs with a class like the following:
public class Person
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string[] Friends { get; set; }
}
3) Create e new controller code file PersonController.cs with methods for getting, inserting and updating records of the database. All the necessary serialization/deserialization (JSON and XML) and data binding is done automatically by the Web Api environment set by the project template.
// Get all the records of persons
public IList<Person> Get()
{
// read database into a list of persons (List<Person>)
// return List<Person>
}
Return record of a selected person:
public Person Get(int id)
{
// read database for a selected person
}
Parameter binding (reading a JSON/XML content sent by http POST into an object, or into a list objects) is also done automatically, as easy as the following:
// parameter binding: Create a Person object with content from XML/JSON
public void ReadPerson(Person p)
{
Trace.WriteLine(Person.Id);
}
public void ReadPersonList(List<Person> plist)
{
Trace.WriteLine(plist.Count);
}

ASP.NET MVC - Complex Objects and Forms

So let's say we have a domain object such as the following
public class Person
{
public string Name { get; set; }
public IList<PhoneNumber> PhoneNumbers {get; set; }
public IList<Address> Addresses { get; set; }
}
The Person is not valid until a name, phone numbers, and addresses have been entered. How do you guys handle this using ASP.NET MVC and forms...
I was thinking you could serialze the Person to session and have multiple views for editing Name, adding phone numbers, adding addresses - the controller actions would modify the person in the session and a final Save action would push to database.
I don't really like having multiple views and using the session. Another option would be to have a single very complex form that could have "dynamic" sections of elements for adding/removing phone numbers, addresses within the browser prior to posting to the save action.
What is everyone doing with complex objects and editing via forms?
Thanks!
I would usually use the "dynamic section" route.
However, I would not make your validation so strict that the user is unable to save work in progress. A list of phone numbers, addresses, etc., can take quite a while to enter. It is beneficial to the end-user to be able to save their work from time to time in case they lose Internet connectivity or something. It's probably a good idea to save the records automatically via AJAX from time to time if your data entry form is quite large. (Like Gmail.) Therefore, your model should allow them to save incomplete work from time to time, and run the whole validation only when they say they are "done."

Resources