Silverlight 3 Validation MVVM WCF EF - wcf

My application is SL2 reading and writing data through an Entity Framework Model exposed via WCF. We have resisted writing any UI validation due to the exicting new validation controls coming from SL3.
...However after doing a trial update on our project yesterday, we realised that most of the standard practices for attaching validation properties to business objects can't readily be applied when the objects are created from the EF model.
Has anyone had any similiar experiences yet, if so how did you work around this?
Thanks,
Mark

You are correct, you have 2 options.
In your model, or viewmodel, depending on your implementation of MVVM, in the setters for your properties, do some validation there, and throw an exception if there is a problem, then use SL3 ValidatesOnException property in your databinding on the view for each control being validated.
use MetaDataClasses to provide addon functionality to ur existing domain model
[MetadataClass(typeof(MyMetadataClass))]
public partial class MyClass
{
public int MyProperty { get; set; }
}
public class MyMetadataClass
{
[Range(1,100)]
public int MyProperty{ get; set; }
}

Related

ControllerContext.ParentActionViewContext in asp.net core

How can I access ParentActionViewContext in Asp.Net Core, I used following commands, but in core they are not available.
ControllerContext.ParentActionViewContext.RouteData.Values["controller"].ToString();, ControllerContext.ParentActionViewContext.ViewBag.Model as MyViewModel
I was not able to find anything regarding these due to scarcity of information on .Net Core.
Thanks in advance.
To get route data, you need to use ControllerContext.ActionDescriptor instead of ControllerContext.ParentActionViewContext now:
ControllerContext.ParentActionViewContext.RouteValues.Values;
Regarding getting Model. Controller class has own properties:
public dynamic ViewBag { get; }
public ViewDataDictionary ViewData { get; set; }
so you may use
var myModel = this.ViewData.Model as MyViewModel;
You cannot find ParentActionViewContext because there are no Child Actions in ASP.Net Core. They have been replaced by View Components.
You can just invoke them and pass any data you want, without going through the request pipeline again (i.e. no model binding, filters or independent http context)
There is a nice introductory article for the topic here

How to deserialize data from ApiController

I have some POCO objects that are set up for use with Entity Framework Code First.
I want to return one of those objects from an ApiController in my ASP.NET MVC 4 website, and then consume it in a client application.
I originally had problems with the serialization of the object at the server end, because the Entity Framework was getting in the way (see Can an ApiController return an object with a collection of other objects?), and it was trying to serialize the EF proxy objects rather than the plain POCO objects. So, I turned off proxy generation in my DbContext to avoid this - and now my serialized objects look OK (to my eye).
The objects in question are "tags" - here's my POCO class:
public class Tag
{
public int Id { get; set; }
public int ClientId { get; set; }
public virtual Client Client { get; set; }
[Required]
public string Name { get; set; }
[Required]
public bool IsActive { get; set; }
}
Pretty standard stuff, but note the ClientId and Client members. Those are EF Code First "navigation" properties. (Every tag belongs to exactly one client).
Here's what I get from my ApiController:
<Tag xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/Foo">
<Client i:nil="true"/>
<ClientId>1</ClientId>
<Id>1</Id>
<IsActive>true</IsActive>
<Name>Example</Name>
</Tag>
The Client member is nil because having disabled proxy generation I don't get automatic loading of the referenced objects. Which is fine, in this case - I don't need that data at the client end.
So now I'm trying to de-serialize those objects at the client end. I had hoped that I would be able to re-use the same POCO classes in the client application, rather than create new classes. DRY and all that. So, I'm trying:
XmlSerializer xmlSerializer = new XmlSerializer(typeof(Tag));
var tag = xmlSerializer.Deserialize(stream);
But I've run into two problems, both of which are due to EF Code First conventions:
Problem 1: Because my Tag class has a Client member, the XmlSerializer is complaining that it doesn't know how to de-serialize that. I guess that's fair enough (though I had hoped that because the member was Nil in the XML it wouldn't care). I could pass in extra types in the XmlSerializer constructor, when I tried that, it then complained about other classes that Client uses. Since Client references all sorts of other objects, I'd end up having to pass in them all!
I tried using the [DataContract] and [DataMember] attributes to remove the Client member from the XML (by not marking it as a DataMember). That did remove it from the XML, but didn't stop the XmlSerializer from whining about it. So I guess it's not the fact that it's in the XML that's the problem, but that it's in the class definition.
Problem 2: When I did try passing in typeof(Client) as an extra type, it also complained that it couldn't de-serialize that class because it contains an interface member. That's because - again due to EF Code First conventions - it has a Tags member as follows:
`public virtual ICollection<Tag> Tags { get; set; }`
So it looks like even if I get over the referenced-types problem, I'm still not going to be able to use my POCO classes.
Is there a solution to this, or do I have to create new DTO classes purely for use at the client side, and return those from my ApiController?
I just tried using DataContractSerializer instead of XmlSerializer, and for the Tag class that seems to work. I've yet to try it with a class that has a virtual ICollection<T> member...
Update: tried it, and it "works". It still manages to reconstruct the object, and leaves the ICollection member at null.
Update 2: OK, that turned out to be a dead end. Yes, it meant that I could correctly serialize and de-serialize the classes, but as everyone kept telling me, DTO classes were a better way to go. (DTO = Data Transfer Objects - classes created specifically for transferring the data across the wire, probably with a subset of the fields of the original).
I'm now using AutoMapper (thanks Cuong Le) so that I can easily transform my POCO entities into simpler DTO classes for serialization, and that's what I'd recommend to anyone faced with the same problem.

asp.net mvc without entity framework

I am learning asp.net mvc and went through a great tutorial that demonstrated it. The tutorial also used Entity Framework.
We have our own data access class which I have to use.
I am a little bit confused as to what I need to do to bridge the gap between our class and MVC framework.
For example, in the tutorial, inside of MovieController.cs file, there is a Edit method, that looks like this:
[HttpPost]
public ActionResult Edit(Movie movie)
{
if (ModelState.IsValid)
{
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(movie);
}
If I don't use the Entity framework, what would it look like? Will I still need to use ModelState.IsValid and save the state like it's done
db.Entry(movie).State = EntityState.Modified;
Please advise. A clearly written example of using asp.net mvc without the use of Entity framework would be great.
What I need to know is what role does state play here and whether it is mandatory to use or is it just a part of how the Entity framework operates.
I would re-write this as:
[HttpPost]
public ActionResult Edit(Movie movie)
{
myDBObject.SaveChanges();
return RedirectToAction("Index");
}
Where myDBObject is my custom database access object.
The examples you see out there where controllers use directly some data access framework such as Entity Framework are bad examples. The whole internet is polluted with such stuff. I can hardly look at it without having my eyes hurt. I consider those as bad practices. Data access should be separated and abstracted in a repository. So for example:
public interface IMoviesRepository
{
Movie Get(int id);
void Save(Movie movie);
}
then you could have some implementation of this interface using plain ADO.NET, EF, NHibernate, a remote web service call, some custom ORM or really whatever:
public class MyCustomFrameworkMoviesRepository: IMoviesRepository
{
...
}
and the controller will take this repository interface as constructor argument:
public class MoviesController: Controller
{
private readonly IMoviesRepository _repository;
public MoviesController(IMoviesRepository repository)
{
_repository = repository;
}
public ActionResult Index(int id)
{
var movie = _repository.Get(id);
return View(movie);
}
[HttpPost]
public ActionResult Index(Movie movie)
{
if (!ModelState.IsValid)
{
return View(movie);
}
_repository.Save(movie);
return RedirectToAction("Success");
}
}
and the last part is to configure your dependency injection framework to pass the correct implementation of the repository into the controller. Now as you can see the way the data is fetched is completely decoupled from the controller logic. It is the way it should be. Always try to avoid the strong coupling between the different layers of your application.
And to answer your question about the State property : this is something completely specific to EF, seeing something like this in a controller is a really pity.
And to bring this even further and improve it you would introduce view models. View models are classes which are specifically designed to meet the requirements of a given view. So for example Movie is a domain model. Domain models should never be directly passed to views. Controller actions should never take domain models as action arguments. You should define view models which will contain only what is required by the given view and then perform the mapping between the view models and the domain models. Frameworks such as AutoMapper make this very simple.
hmm.
MVC and entity framework really have nothing to do with each other; they just work well together.
the if (ModelState.IsValid) validates your view model. If you are not using view objects with validators, it's a little pointless; if you are, then it's quite valuable.
inside the if (ModelState.IsValid) brackets, you would take the post data from your web page (usually a view model) and apply it to the object that will persist it to the database. EF is often used because once it's set up, it's fairly easy to maintain, and a lot less code to write.
db.Entry(movie).State = EntityState.Modified;
db.SaveChanges();
are both EF-related. These would need to be replaced by your repository class methods and objects.
return RedirectToAction("Index");
is MVC. Upon successful persistence to your data store, return the control to the index page.
return View(movie);
is used to redirect back to the original view, because something failed validation.
You would still check ModelState.IsValid, but otherwise your code would look like what you have.
This assumes that your model has DataAnnotations attributes on it, though, which is what ModelState.IsValid is using to check. Those attributes can be used on any C# class' properties - not just Entity Framework.
You might end up creating specific view models for this purpose.
You need to make some connection between the Movie object (passed in on the http POST) and your database methods (myDBObject).
Maybe you want to say myDBObject.SaveChanges(movie) and assuming your db code knows how to handle the object Movie then you'll be fine.

Alternatives to metadata buddy classes in Silverlight?

I am trying to seperate DataAnnotations from our POCOs within a Silverlight project. One way to do this outside of SL is to use buddy classes e.g:
[MetadataTypeAttribute(typeof(MyPOCO.POCOMetaData))]
public partial class MyPOCO
{
internal sealed class POCOMetaData
{
[Required(ErrorMessage="Requires name.")]
public string Name { get; set; }
[Required(ErrorMessage = "Requires age.")]
public string Age { get; set; }
}
}
However as of Silverlight 4, the MetadataType attribute does not exist within System.ComponentModel.DataAnnotations namespace. Has anyone found an alternative way to seperate DataAnnotation attributes from POCOs? I am looking into this as I was planning on using T4 templates to generate our basic POCO classes.
This scenario looks somehow strange, why wouldn't you want to decorate your POCOs themselves?
1 - If there is a matching server, consider using WCF RIA Services and declare your POCOs at the server side, the RIA engine will then generate for you all the proxies at the client side, including all its annotations, and many other goodies.
2 - If there is no matching server and you want to manipulate the data on client side, then I would go for WPF and have a wider range of desktop development capabilities.
3 - Unfortunately, TypeDescriptor is also not implemented in Silverlight, so you can't even add the attributes dynamically at runtime (in case you would want go that dirty-handed).
So I'm affraid your chances are:
Attach the MD to partial classes
Decorate your POCOs
Use WCF-RIA and declare the POCOs at the server-side
Go WPF
Please take a look on PEM. the EDMX designer can be extended, maybe the class designer can be extended too (oops, unfortunately seems it isn't).
Suggest to the SL team for this feature to be implemented.

Objects returned from WCF service have no properties, only 'ExtentionData'

Im am not new to WCF web services but there has been a couple of years since the last time I used one. I am certain that last time I used a WCF service you could determine the type of object returned from a service call when developing the code. EG;
MyService.Models.ServiceSideObjects.User user = myServiceClient.GetUser();
You were then free to use the 'user' object client-side. However now it seems as if the WCF service will not return anything more than objects containing basic value types (string, int ect). So far I have remedied this by defining transfer objects which contain only these basic value types and having the service map the complex 'User' objects properties to simple strings and int's in the transfer object.
This becomes a real pain when, for example you have custom type objects containing more complex objects such as my Ticket object.
public class Ticket
{
public Agent TicketAgent {get;set;}
public Client Owner {get;set;}
public PendingReason TicketPendingReason {get;set;}
}
As simply mapping this object graph to a single transfer class with a huge list of inter-related system-typed properties gives a very 'dirty' client-side business model. Am I wrong in thinking that I SHOULD be able to just receive my Ticket object from a service method call and deal with it client side in the same state it was server-side ?
I realise this is probably a violation of some SoA principal or similar but my desktop app currently consuming this service is the ONLY thing that will consume ever consume it. So i do not care if many other clients will be able to manage the data types coming back from the service and therefore require some hugely normalised return object. I just want my service to get an object of type Ticket from its repository, return this object to the client with all its properties intact. Currently all I get is an object with a single property 'ExtentionData' which is unusable client-side.
Hope this makes sense, thank you for your time.
I might've missed a memo, but I think you need to decorate your model classes with DataContractAttribute and your properties with DataMemberAttribute, like so:
[DataContract( Namespace = "http://example.com" )]
public class Ticket
{
[DataMember]
public Agent TicketAgent { get; set; }
[DataMember]
public Client Owner { get; set; }
[DataMember]
public PendingReason TicketPendingReason { get; set; }
}
This is why you probably want to set up a DTO layer, to avoid polluting your model classes.
As for ExtensionData, it's used for forward-compatibility: http://msdn.microsoft.com/en-us/library/ms731083.aspx
I have marked Niklas's response as an answer as it has solved my issue.
While it seems you do not NEED to use [DataContract] and [DataMember], in some cases, I believe it could cause the issues I was experiencing. When simply transferring custom typed objects which, in themselves, only have simply typed properties, no attributes needed. However, when I attempted to transfer a custom typed object which itself had collections / fields of more custom typed objects there attributes were needed.
Thank you for your time.