I have existing code that uses System.Configuration.Provider namespace for provider collections to plugin various implementations of interfaces, where multiple implementations exist in the collection and are selected by name according to various logic.
This namespace is not available in .net core, so I'm looking for advice on how to implement a replacement solution that will work with .net core framework.
I know that if I was just trying to plugin one implementation, I could do it by dependency injection. But I'm looking for a way to have multiple implementations available to choose based on name.
My current implementation with provider model populates the provider collection from a folder where you can drop in xml files that declare the type of the actual implementations, so new implementations of the provider can be loaded from an assembly by just adding another file to the folder. I'd like to keep the logic as similar as possible to that but I'm open to json files rather than xml.
I am thinking I could load up a collection of implementations of the interface from json files in Startup and use dependency injection to provide the collection where needed or perhaps an interface that can get the collection would be lighter weight and allow getting them when they are needed rather than at startup.
Is that the right approach? Anyone have better ideas or done something similar?
This is done more generically than using an abstract base class like ProviderBase in the new framework. You can register multiple of the same service with the DI framework and get them all either simply by asking for an IEnumerable<> of the type you register them as or using the GetRequiredServices<> extension method. Once you get your services, however, you'll need some other way of distinguishing them, such as a property indicating a unique name, which is the pattern the ASP.Net team has been following.
You can see an example in the Identity framework v3 with the Token Providers.
IUserTokenProvider<T>, the "provider"
UserManager, which consumes the token managers
Related
There is a requirement:
For each RESTful resource method, there is a set of OXM metadata file. I need to load those files while creating JAXBContext. So I need to know per-request ResourceInfo, and then mapping from some Annotation on the Resource Method, which can indicate which set of OXM metadata file should be loaded.
Is ResourceInfo per-request?
Can I obtain the Method (resource method) per request inside EntityProvider, such as MessageBodyReader and MessageBodyWriter?
Which do you prefer, OXM metadata between JPA Entity and XML/JSON or between TO and XML/JSON? Since I assume per service TO can customize the view of domain class to client.
I had similar problem. After several hours of research I got what I want by directly injecting provider capable to resolve resource method:
#Inject
Provider<RoutingContext> routingContextProvider;
log.info("routing method == " + routingContextProvider.get().getResourceMethod());
After a few research and experiments, finally I made the breakthrough.
Is ResourceInfo per-request?
[ANS] Yes, as documented in javadoc.
Can I obtain the Method (resource method) per request inside EntityProvider, such as MessageBodyReader and MessageBodyWriter?
[ANS] There is a defect in JIRA which is very similar with this, it says that ResourceInfo cannot be injected into Filters, interceptors as found, maybe it will be fixed at some version for glassfish.jersey team.
Which do you prefer, OXM metadata between JPA Entity and XML/JSON or between TO and XML/JSON? Since I assume per service TO can customize the view of domain class to client.
[ANS] Finally I decide to use TO other than JPA Entities as a concept of module exports. Because their development lifecycle are different, and there is also some restrictions to use JPA Entity with OXM.
a. Development Lifecycle: TO is designed as exportable with interfaces to other modules or upper layer services, they are suppose to be determined while case designing phase according to requirement, and since it's delivered with interface, the content of TO should be relatively stable, changes should also follow versioning management. But entity design is much more flexible, and it changes time to time, those changes should be hide from the clients of this module, and sometime there is business logics inside. I know there are some company or architecture expose entities to other modules, or there is only 1 module, so it does not matter. But I choose to hide domain classes.
b. While using JPA Entity exposing at service layer, then MOXy can be a good choice with providing Mapping JPA Entity and RESTful Entity body. Then due to some Lazy Loading requirement, ORM frameworks does some class transformation or byte code generation work implicitly, and some additional Lazy loading related fields will be loaded at runtime or generated at compile time, and those fields will lead some boring errors in MOXy while OXM using FIELD as accessor-type. You have to switch to PROPERTY mode or to define the god-know fields in your OXM metadata to hide them. Otherwise Getters and Setters had to be defined on JPA Entity class, which will lead to additional exposure.
And introduce TO will reduce the complexity of OXM work, much less metadata files will be used, with annotations on TO class, there can be zero OXM Metadata files, and I think OXM Metadata files are designed to integrate different systems other than connecting modules inside one system. So the answer is :
I PERFER TO than JPA Entities.
I have a question using Entity Framework in WCF. I am using .NET 4.5 with EF DbContext.
Here are the things I know to do to use EF in WCF. May be they are insufficient or some are not required.
Create EF ADO.NET Model.
Seperate the POCO classes to a seperate project (ProjectName: Entities) by using DbContext template generator.
Point the TT template of the POCO project to the edmx file in the data project (ProjectName: Data). "..\Data\MyEdmx.edmx"
Add [DataContract(IsReference(True))] and [DataMemeber] attributes in the .TT file of the POCO project so that the classes and properties will have the serialization attributes. Add Runtime.Serialization reference to the project and add the namespace to .TT file. This enables not to lose your attribute declaration while recreating the classes on a save of the .TT file or adding new entities.
Add ProjectName: Entities reference to Data project.
Turn off ProxyCreation and LazyLoading in the Context.tt file in the data project.
Add (ProjectName: Entities) and (ProjectName: Data) to your wcf service project.
Copy the EntityFramework connection string to your WCF project.
All your select methods in the service, must use .Include if you want the navigation objects to be populated. This gives better control when you want to load or or when you want limit data to show. Also, you don't get the child/related automatically due to lazyloading turned off.
Insert or Update or Delete, the service has to create the context and manually set the object state to be modified or added? Otherwise the changes will not be saved. Use the DbContext.Attach to attach and set the state of the entity appropriately Added,Modified, etc.
The problem I had was I could not find a good example of the steps to perform to use EF with WCF. I was able to see only bits and pieces. May be I am a late entrant to the WCF EF world hence could not find.
Not sure if I can use proxies WCF. I haven't understood completely the advantage of proxies yet.
I also read recommendations to use DTO as a layer between EF and the service. This requires a mapper to be in place. I don't know if I need it right away. But the idea is clear that it helps hide any unnecessary database columns showing in the business object. For example, audit columns such as created by, updated by etc we dont to show in the client.
I did not choose to use DataServices as I lose other binding options that I get from WCF. I don't know if it is a good thing to lose the simplicity of DataServices thinking about the future requirements of clients that require/support other binding mechanisms.
Any recommendations is appreciated.
Additional Update
I did find this in MSDN http://msdn.microsoft.com/en-us/library/ee705457(v=vs.100).aspx. Some of the links were pointing to pre-release documentation. But this gives some more ideas for me in using EF and WCF.
This articles shows how to use proxies with WCF, change tracking of POCO. This is a good start for me. If any one has more advise please provide your thoughts.
Update 2
*Another Excellent Link for N-Tier*
http://msdn.microsoft.com/en-us/magazine/dd882522.aspx
I am glad that the time I am spending is really educating me!
I progressed on using EF with WCF after lot of reading here and in other forums.
I followed the steps ahead. I was able to see the advantage of using DTO. This really allows you to hide fields that you don't need to expose to the client or other services. But I am holding back on introducing DTO due to time constraints.
I used context.Attach, context.Add and context.Entry.
I also did a small prototype to use WCF Data Service. That was very fast paced development. I am holding back on using WCF data services for now due to time constraint in learning its features.
I have a WCF Data Service layer that is exposing POCO entities generated by the POCO T4 template. These POCO entities are created in their own project (i.e. Company.ProjectName.Entities) because I'd like to share them wherever possible.
I have a set of interfaces in another project (Company.ProjectName.Clients) that reference these POCO types by adding an assembly reference to the Company.ProjectName.Entities.dll. One of the implementation of these interfaces is a .NET client that I want to consumes the service using the WCF Data Service Client Library.
I've used the Add Service Reference to add service reference. This generated the DataServiceContext client class and the POCO entities that are used by the service. However, these POCO types gemerated by the Add Service Reference utility now have a different namespace (i.e. Company.ProjectName.Clients.Implementation.WcfDsReference).
What that means is that the POCO types defined in the interfaces cannot be used by the types generated by the utility without have to cast or map.
i.e. Suppose I have:
1. POCO Entity: Company.ProjectName.Entities.Account
2. Interface: interface IRepository<Company.ProjectName.Entities.Account>{....}
3. Implementation: ServiceClientRepository : IRepository<Company.ProjectName.Entities.Account>
4. WcfDsReference: Company.ProjectName.Clients.Implementation.WcfDsReference
& Company.ProjectName.Clients.Implementation.WcfDsReference.Account
Let's say I want to create a DataServiceQuery query on the Account, I won't be able to do this:
var client = new WcfDsReference(baseUrl);
var accounts = client.CreateQuery<Company.ProjectName.Entities.Account>(...)
OR: client.AddToAccounts(Company.ProjectName.Entities.Account)
, because the CreateQuery<T>() expects T to be of type & Company.ProjectName.Clients.Implementation.WcfDsReference.Account
What I currently have to do is to pass the correct entity to the CreateQuery method and have to map the results back to the type the interface understands. (Possible with a mapper but doesn't seems like a good solution.)
So the question is, is there a way to get the Add Service Reference utility to generate methods that use the POCO types that are in the Company.ProjectName.Entities namespace?
One solution I am thinking of is to not use the utility to generate the DataServiceContext and other types, but to create my own.
The other solution is to update the IRepository<T> interface to use the POCO types generated by the utility. But this sounds a little bit hacky.
Is there any better solution that anyone has come up with or if there's any suggestion?
Ok, a few hours after starting the bounty I found out why it wasn't working as expected on my end.
It turns out that the sharing process is quite easy. All that needs to be done is mark the model classes with the [DataServiceKey] attribute. This article explains the process quite well, in the 'Exposing another Data Model' section
With that in mind, what I was trying to do is the following:
Placing the model on a separate class library project C, sharing it with both webapplication projects A and B
Create the data service on project A
Add the service reference on project B
Delete the generated model proxies out of the service reference, and update it to use my model classes in project C
Add the DataServiceKey attribute to the models, specifying the correct keys
When I tried this it did not work, giving me the following error:
There is a type mismatch between the client and the service. Type
{MyType} is not an entity type, but the type in the
response payload represents an entity type. Please ensure that types
defined on the client match the data model of the service, or update
the service reference on the client.
This problem was caused by a version mismatch between project C (which was using the stock implementations on the System.Data.OData assemblies) and the client project B that was calling the service (using the Microsoft.Data.OData assemblies in the packages). By matching the version on both ends, it worked the first time.
After all this, one problem remained though: The service reference procedure is still not detecting the models to be shared, meaning proxies are being created as usual. This led me to opt out of the automatic service integration mechanic, instead forcing me to go forward with a simple class of my own to serve as the client to the Wcf Data service. Basically, it's a heavily trimmed version of the normally autogenerated class:
using System;
using System.Data.Services.Client;
using System.Data.Services.Common;
using Model;
public class DataServiceClient : DataServiceContext
{
private readonly Lazy<DataServiceQuery<Unit>> m_units;
public DataServiceClient(Uri _uri)
: base(_uri, DataServiceProtocolVersion.V3)
{
m_units = new Lazy<DataServiceQuery<Unit>>(() => CreateQuery<Unit>("Units"));
}
public DataServiceQuery<Unit> Units
{
get { return m_units.Value; }
}
}
This is simple enough because I'm only using the service in readonly mode. I would still like to use the service reference feature though, potentially avoiding future maintenance problems, as evidenced by the hardcoded EntitySet name in this simple case. At the moment, I'm using this implementation and have deleted the service reference altogether.
I would really like to see this fully integrated with the service reference approach if anyone can share a workaround to it, but this custom method is acceptable for our current needs.
I want to download xsd specifications from a web service and automatic converting (serialize) these schemas to classes (visual studio - vb.net). If the organization that is responsible for the xsd schemas alter them in a way that only my class corresponding to the xsd have to be altered (not the rest of my code) I would like to automatic update my xsd corresponding class. Is this possible? If so, can somebody tell me how to do it?
Thanks!
I use vs2010. What I want to do is: call a web service where I can send in an input parameter to the service which specifies the xsd I want to retrieve (the service is GetShemaDefenition and returns an object with the schema specification in a string property of the object). I den have to read the xsd string from the string property and convert this to a class representation of this xsd specification. Is it possible to do this automatically? I have done this manually by using xsd.exe. If the owner organization of the xsd has altered the xsd specification, I have to test if there is a new specification, and if there is I have to build a new class representation of this xsd? Is it possible to do what I want? And how would I know if it has been a big change in the xsd which also affect other parts of my code, not just the class representation of the xsd?
Tanks a lot for your reply! So what you are saying, if I understand you correct, is that there is not a good solution for automating this functionality because if the xsd change I most likely (in some occasions’) have to change my code manually? So I have to choose, either in my application or in my intermediate service? But what is the purpose for providing the xsd in a web service? What can I use the web service for? I just wondering, maybe it is clear but I am new to web services and is eager to learn more.
Update:
Thanks! But can you explain a little bit more. What I have to do is: I use one web service where one of the properties is a string. The string is an XML inside a CDATA block. The organization which provides the web service will not pares the xml inside the CDATA block but instead forward this to another organization that will use the xml data. The organization which uses the xml data specifies the xsd schem that I have to follow to generate my xml correct. This is the xsd schema I can get from another web service. I don’t really understand what I can do with this xsd file from the web service. What can I do with it and why do I want to download it from the web service, when I can’t use it automatically? Because I have to manually do the changes when the xsd changes I can easily download the xsd schema from the organization’s home page and make the new class with xsd.exe. I understand there is something I don’t understand :o), can you pleas clarify?
What visual studio version you are using?, Normally you can click on the project's references and Add Web service. In this case Visual studio creates automatically the objects required to consume the service. you can update it any time by a right click on the reference.
However if it is very likely to change often, One solution is to implement an adapter class. use create an interface that provides the same functionality and call the actual web service. In your application you use only the proxy class and not the Web Service. Later when the web service interface changes all you have to do is to change the internals of this intermediate class.
Update:
you can use this tool to create you object model in code. Then you can compile your new object model and use it in you application. There are many complications in what you want to do and the bottom line is; when the object model changes, your code will fail. There is absolutely no way to imagine how the interface will change so while you can do all that automatically there is nothing to do if the name of a function changes.
However the answer to your situation is indirection. If you can't guaranty the stability of a external service. Why not create a stable intermediate service that calls the actual one? this way in future you don't need to touch you application. All you have to do is to modify the intermediate service while keeping it's interface compatible.
I am creating a set of Web Services which share some common xml defined data elements.
I want to separate these entities into a common schema, service 1 specific schema, service 2 specific schema etc... the service specific schemas will reference the common schema. I
want to use svcutil /datacontractonly to generate classes that can be used to create and serialize these objects using the WCF web programming model. The problem I am having is that
when I import the common schema into the service specific schemas the common schema entity classes are included in the code generated for the service specific classes. This causes
compile errors later when a single client attempts to use the generated entity classes for two services which both use the common schema entities. Is there anyway to get svcutil to only include the service specific entities in the generated code? I'd just like to have a common dll which includes the common schema entities which the services may reference.
I think this is what you need (on svcutil options)
/reference:
References types in the specified assembly. When generating clients, use this option to specify assemblies that might contain types that represent the metadata being imported.
You cannot specify message contracts and XmlSerializer types using this switch.
If DateTimeOffset referenced, this type is used instead of generating a new type. If the application is written using .NET Framework 3.5, SvcUtil.exe references DateTimeOffset automatically.
Short Form: /r
here is where I found it