Asynchronous Begin/End pattern for webservices in silverlight project - silverlight

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.

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.

Common EJB Client Jar for various modules under the same EAR

Hello brothers in code!
First question here so I'll try my best to respect all the standards. Correct me if I skip anything and I'll fix it right away.
I'm kind of confused about the approach I should take with my application. I have several EJB projects and JSF projects under the same EAR and, of course, I'd like to define some local interfaces for all of the EJB projects. I have a persistence layer with a couple of modules insipierd by the EAO pattern and an access point to the bussiness layer through a Session Façade.
My intention is to make a "SharedInterfaces" Jar that contains all the Client interfaces (All EJB Client jars in one, if I must say) and all the Interfaces that the entities will implement so I can abstract the projects between themselves (no dependencies, just common interfaces to work together).
How can I turn this "SharedInterfaces" project into a common EJB CLient Jar to be used by all the modules? On the other hand, I can make some interface extension so I don't have to configure a project... still I'm not sure if this common project is on the "best practices" approach.
Well, I pretty much figured it out myself.
The SharedInterfaces project defines the interfaces to be commonly used and when I want to make a LocalInterface for an EJB I simply leave that interface blank and extend the one I defined on SharedInterfaces. The container seems to handle it allright because the interface is a local interface after all (sort of).
Just for the sake of clarity I'll add a simple example of what I did. This is the local interface I create for an EJB:
package org.myapp.managers;
import javax.ejb.Local;
#Local
public interface UserManagerLI extends IUserManager{
}
Then, on SharedInterfaces I simply add the interface IUserManager:
public interface IUserManager {
public IUser newUser();
public void saveOrUpdate(IUser u, boolean hashPass);
public void deleteUser(IUser u);
public boolean checkUserAvailability(String username);
public IUser getUser(String username);
}
Then, to use it I simply made the injection as usual:
#ManagedBean
#SessionScoped
public class LogInBean {
#EJB
private IUserManager userManager;
// Attributes, Setters, Getters and methods
}
Of course, one should ALWAYS be careful about what does he expose. Thinking of the interfaces as contracts of service, one should not be able to access functions he is not supossed to access.

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(....);
}

Is possible in WCF service: method return IList<object> when object can be Person class?

Is possible in WCF service: method return IList when object can be Person class?
Ex: in IServiceContract.cs
[ServiceContract]
public interface IDAS
{
[OperationContract]
void DoWork();
[OperationContract]
List<object> GetAnyClass();
}
And class:
public class DAS : IDAS
{
public void DoWork()
{
}
public List<object> GetAnyClass()
{
List<Person> a = new List<Person>();
a.Add(new Person());
return a;
}
}
The problem at runtime is:
System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error
Theoretically yes, although you need to tell the service that it might be expecting a Person object using the KnownTypeAttribute on your method.
[OperationContract]
[KnownType(typeof(Person))]
List<object> GetAnyClass();
I would really think twice about doing this in practice though - instead declare different method signatures for the objects you're expecting to return:
[OperationContract]
IList<Person> GetPeople();
[OperationContract]
Person GetPerson();
[OperationContract]
IList<Book> GetBooks();
[OperationContract]
Book GetBook();
etc.
It's supposed to be a contract, i.e. concrete, so if you suddenly change the type of class you return it can really mess the clients up.
Also in your example you were returning a concrete List class - this should be avoided, instead use either IList<> or Collection<>.
Yes it is possible, you need to update the reference in Visual Studio (or whatever you are using to generate the proxy class with) and change the collection type returned. There is an option in 'Configure Service Reference' and you can select Generic.List in there (right click your WCF service reference).
The mismatch is because you have changed your service on the server end and not got a new proxy. So change it to return a Generic.List and then regenerate using the steps in 1.
Hope that helps
Ryan
You can return an IList but it's definitly not a good approach to take.
When you expose your services you need people at the other end of the service to know what they are getting.
IList<Person> would be clearer for everybody that use the services or that code in the services.
If you need a method that can return different type of object just split them out in multiple operations.
IList<Person> GetPersons(...)
IList<Animal> GetAnimals(...)
My 2 cents.
Cheva (et al),
There is nothing stopping you from calling a single method to fill in the collection(s) you return from the service calls.
IList<Person> GetPersons(...)
IList<Animal> GetAnimals(...)
Both GetPersons() and GetAnimals() can certainly call an internal method e.g.
IList<Animal> GetAnimals(...)
{
// get list of objects of a given type
internalIList<Object> genericResults = GetItems(
ItemType.Persons|ItemType.Animals );
...
IList<Animal> results;
// convert to specific type
results = new IList<Animal>(genericResults);
return results;
}
That should work, but I didn't test it or anything. YMMV. ; )
-Scott

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