Silverlight serialisation/deserialisation problem - silverlight

I'm looking for a way to persist Silverlight objects to a user's PC, then re-hydrate them so the user can finish editing them.
Serialising with DataContractSerializer and persisting to IsolatedStorageFile works fine. However, deserialising causes a problem. Here's the code that causes the failure:
private string _FirstNames = string.Empty;
public string FirstNames
{
get { return _FirstNames; }
set
{
new PersonNameValidator().Validate(value); //<-- BOOM 8(
Set(ref _FirstNames, value, () => this.FirstNames);
}
}
The deserialiser calls the property setter, which in turn throws an exception and aborts the deserialisation.
I've tried explicitly applying DataContract/DataMember/IgnoreDataMember attributes, but then it doesn't play nicely with private fields:
System.Security.SecurityException
occurred Message="The data contract
type
'Trident.Model.Journey.JourneyApplication'
cannot be serialized because the
member '_TravellerSavingsAmount' is
not public. Making the member public
will fix this error. Alternatively,
you can make it internal, and use the
InternalsVisibleToAttribute attribute
on your assembly in order to enable
serialization of internal members -
see documentation for more details. Be
aware that doing so has certain
security implications."
How can I bypass the property setters during deserialisation?
I'd like to keep my classes focused on the domain, and not too polluted with infrastructure concerns.

A couple of ideas:
serialize a property that is used only for serialization thereby bypassing any validation
serialize a parent class and use a derived class for validation

Related

Recovering after exception when using a single dbcontext

I am using entity framework to persist data in a N-tier Wpf application. My dbcontext is shared amongst all repositories and is never disposed. When I persist data I mark an object as modifed and try to save changes. If an error accurs while persisting the object the object is still markted as modifed and if the user aborts the current opperation he will get the same error when saving another object.
I have solved this by overriding SaveChanges in my dbcontext and if any error accurs I accept all changes(see code below). So if an error accurs the object and all objects are marked unchanged even if theyr'e not persited.
This doesn't feel right...
Does anyone agree with this solution?
Another solution would be to new the dbcontext in each method in my repositores and disposing of them right away. That will make my repositories more complicated and "noicy" and I will also lose the ability to lazy load data...
Does anyone have a different solution for me?
//In my repositories
public void UpdateObject(Object object)
{
dbContext.Entry(object).State = EntityState.Modified;
dbContext.SaveChanges();
}
//In my dbcontext class
private ObjectContext ObjectContext()
{
return (this as IObjectContextAdapter).ObjectContext;
}
public override int SaveChanges()
{
try
{
return base.SaveChanges();
}
catch (Exception)
{
ObjectContext().AcceptAllChanges();
throw;
}
}
Our team uses an approach similar to below:
Repository:
public class StudentRepository
{
private readonly MyEntities _context;
public StudentRepository(MyEntities context)
{
_context = context;
}
// Basic CRUD methods etc
}
Business Logic:
public AddStudent(Student student)
{
using( var context = new MyEntities())
{
var studentrepo = new StudentRepository(context);
studentrepo.Add(student);
context.SaveChanges();
}
}
This is an oversimplified example, but should give you an idea. To reduce code, we also use a base generic repository class for the CRUD methods.
If the project we are working on includes a web service, we instantiate the dbcontext in the API Controller and override the Dispose method to get rid of it.
Having such a long lived context is not a good idea. It will get large and slow with all the entities and changes being tracked, concurrency related issues may arise and exceptions thrown by your context can impact your entire application.
http://msdn.microsoft.com/en-us/data/jj729737
Another solution would be to new the dbcontext in each method in my
repositores and disposing of them right away. That will make my
repositories more complicated and "noicy" and I will also lose the
ability to lazy load data
In a disconnected scenario I would create and dispose with each request/unit of work. Concerned about your repos getting complicated? Then don't use this extra layer of abstraction. Are the repos really necessary? What do you gain over using the DbContext directly?
As for lazy loading I think in a disconnected n-tier scenario that lazy loading is not really appropriate. You should probably use eager loading of required data for your view or have separate method calls to get the related data.

Asynchronous Begin/End pattern for webservices in silverlight project

I found that the proxy generated with SlSvcUtil.exe (or by adding reference to Web References) only supports Event based async model which is absolutely inappropriate from design point of view (events were 2nd class citizens from the first days).
I'm going to implement F#'s async builder approach and I found "old style" Begin/End are much easier to be generalized. I notices SlSvcUtil.exe generates Begin/End methods pair but marks them both with private keyword?
A couple options on top of my head are:
expose Begin/End methods by updating the proxy class by hand
use wsdl.exe and create wrapper library for missing System.Web classes
use other communication protocols (HttpClient, Tcp)
use third-party proxies (failed to find any so far)
Any ideas?
Say someone created a remote service with one method:
public interface CompressService
{
public byte[] Compress(byte[] inData);
}
After SlSvcUtil I got:
public class CompressServiceSoapClient: ClientBase<CompressServiceSoap...
{
private BeginOperationDelegate onBeginCompressDelegate;
private EndOperationDelegate onEndCompressDelegate;
public event System.EventHandler<CompressCompletedEventArgs> CompressCompleted;
public void CompressAsync(byte[] inData, object userState);
}
While in fact I need:
public class CompressServiceSoapClient: ClientBase<CompressServiceSoap...
{
public IAsyncResult BeginCompress(byte[] inData, System.AsyncCallback callback, object asyncState);
public byte[] EndCompress(IAsyncResult result);
}
Answer
The solution is to declare contract interface with async methods and do not use generated code inherited from ClientBase<>. The article http://msdn.microsoft.com/en-us/library/dd744834(v=vs.95).aspx describes this in more details.
You can access the begin/end methods by using the channel factory for the end point.
Basically just create a new ChannelFactory and pass in a binding and end point. You can use the host source to dynamically update the end point so it's not hard-coded. The resulting instance will expose the begin/end methods for you.

Why Don't DomainService Constructor Overloads Show Up as DomainContext Constructor Overloads?

I wrote an overload for my DomainService class. Problem is, when I recompile, it's not showing up as an overload for my DomainContext. What's wrong? Here is a code sample:
[EnableClientAccess]
public class FoodDomainService : LinqToEntitiesDomainService<FoodEntities>
{
public FoodDomainService(CultureInfo cultureInfo)
{
Thread.CurrentThread.CurrentCulture = cultureInfo;
}
}
And this doesn't work:
FoodDomainContext _foodContext = new FoodDomainContext(Thread.CurrentThread.CurrentCulture);
I get an error that there is no overload matching that. Am I not allowed to do this? Do I need an attribute of some kind?
You are not allowed to do this. When newing up the context from your Silverlight client, you are not directly intantiating your service. Instead, you instantiate a proxy class that was generated by RIA Services, and that proxy class will then call your service. This is why you don't see your constructor: because RIA did not generate it in your proxy.
Doing what you're trying to do would also implicate that there is a round-trip to the server at the time of newing up that FoodDomainContext class, which is not going to happen, because you need to complete the initialisation of that object before you can do so.
Anyway, instead of that you can create a method called SetCurrentCulture() and then call it after initializing the proxy.
This will not work because DomainContext is generated on client code of silverlight, click on view all folders or jump to definition and you will see that code generated will not contain your extra constructor.
Instead you will have to create a method in your domain service and pass information to server.
public SetCultreInfo(int lang,...)
{
.. set culture info
}
On your client, inside constructor you should call,
public MyDomainContext()
{
this.SetCulture(....);
}

AppDomain.GetData method not accessible?

I am developing a Silverlight 3 application and I would like to delegate all unexpected error handling in a single instance of a class I have named ErrorHandler. This class has one method named HandleApplicationException, plus a couple of other methods to handle more specialized errors.
In my application I am using Unity for dependency injection, but since I want the error handling object to be available even when the Unity container is not yet set up, I register the object as AppDomain global data in the App class constructor, this way:
public App()
{
this.Startup += this.Application_Startup;
this.Exit += this.Application_Exit;
this.UnhandledException += this.Application_UnhandledException;
AppDomain.CurrentDomain.SetData("ErrorHandler", new ErrorHandler());
InitializeComponent();
}
And in case of unhandled exception, I retrieve the error handler object and use it this way:
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
e.Handled = true;
var errorHandler = AppDomain.CurrentDomain.GetData("ErrorHandler") as ErrorHandler;
Debug.Assert(errorHandler != null, "No ErrorHandler registered.");
errorHandler.HandleApplicationException(e.ExceptionObject);
}
The problem is that the AppDomain.GetData method in the Application_UnhandledException method is throwing a MethodAccessException. I don't understand why, as I am just invoking a public method on the AppDomain class. I have used a similar approach in other applications and it worked fine (anyway these were not Silverlight applications).
So, what's going on? Am I doing something wrong?
Ok, I got it. From MSDN documentation:
This member has a
SecurityCriticalAttribute attribute,
which restricts it to internal use by
the .NET Framework for Silverlight
class library. Application code that
uses this member throws a
MethodAccessException.
I have resorted to storing the error handler in a public property in the App class, then I access it using ((App)Application.Current).ErrorHandler. I don't like doing things this way but I suppose it is ok in this special case.
Why can't you just use a static instance of ErrorHandler? I.e. have something like ErrorHandler.Current?
It looks like you're trying to manually construct a poor man's IoC framework to be honest.
Consider doing some research on Unity/Ninject and see for yourself why strongly-typed decoupling is better.

DeSerialized attribute in Silverlight

I have reasonably limited data to move between silverlight and a WCF service. So I have set up some datacontracts. I was hoping to be able to use the same classes to use for some limited data validation on the client side, without needing the overhead of DTOs and stuff.
I have a contract something like this:
[DataContract]
class MyObject
{
private String _id;
[DataMember]
public String ID
{
get
{
return _id;
}
set
{
_id = value;
DoStuff();
}
}
Now when I deserialize the object the setter will be run. This will set the private variable _id which is good. But I don't want the DoStuff() to be run on deserialization.
I had hoped to use the [OnDeserializing] and [OnDeserialized] attributes. I could have defined a bool flag that I could use to control what gets run in the setter. This actually works on the server side but Silverlight doesn't have those attributes.
Any suggestions?
I would recommend not overloading the usage of these classes to perform logic. This is your service data contract. You shouldn't touch the Silverlight proxy classes that get generated. I recommend that you put your validation logic into other classes that you invoke after deserialization is complete. Otherwise, you might start getting errors in your serialization code when your errors are actually in your data.

Resources