How to connect to OData service with generated OData client? - c#

I generated the client code from a for OData V4 service (Dynamics 365 metadata) using the OData V4 Client Code Generator project template (https://marketplace.visualstudio.com/items?itemName=bingl.ODatav4ClientCodeGenerator).
The code was generated fine and it compiles. Now the problem is that I simply cannot find a way to make a connection (or context) that can be used when querying data (OData linq queries for example).
All the examples I've read basically just "start right away" with having a Context or a Resource available, but none of them actually specify why or how it's there.
For example https://blogs.msdn.microsoft.com/odatateam/2014/03/11/tutorial-sample-how-to-use-odata-client-code-generator-to-generate-client-side-proxy-class/ shows how to generate the classes and then creates an instance of NorthwindEntities (or XxxxEntities) which, again, I don't have generated (I don't have anything named "Entities" in the generated code).
https://stoneridgesoftware.com/working-with-the-odata-endpoint-in-dynamics-365-for-operations/ just simply creates a new instance of Resources class, which I don't have (what is it?). I have nothing named Resources in the generated code.
Obviously it can't be this difficult so maybe I'm missing something.
EDIT: the generated class contains only classes Crmbaseentity, CrmbaseentitySingle, ExtensionMethods and then the entity classes themselves. There simply are no other classes.
Any ideas how to do this differently or any blog posts that I've missed?

The problem was that I used the code generation template from https://github.com/Microsoft/Dynamics-AX-Integration/tree/master/ServiceSamples/ODataUtility. When I added the OData service to the project as a "service refernce" and used the wizard, then the code was generated normally.
I still don't know the actual reason why the T4 template didn't work.

Related

Share classes vs. swagger generated classes

I have an asp.net/Blazor VS solution with three projects,
Shared
asp.net core apis
Blazor webassembly.
I created bunch of classes in Shared project and from the other two projects, made a reference to the Shared project. All is good so far.
Then I used Swagger UI to generated stubs for me so I can interact with the remote APIs. Swagger UI created the Service.cs and Contract.cs which is great. The problem is that Contract.cs has redefined the classes that I have declared in Shared projects under it's own namespace. Now I don't know which to use and which to import. If I use my own Shared classes, then I won't be able to use the APIs from swagger in Service.cs without casting. If I modify Contract.cs, then all my changes will be lost the next time I run Swagger UI.
This also resulted in having two DBContext - 1) the one I defined and 2) The one that swagger defined. Now every time I want to do something, I also have to use --context parameter on the command line to specify which DBContext to use.
The question is how can I use my own classes yet use swagger to make life easy in terms of talking to the remote APIs? What is the best practice here?
When you want to use Swagger (client side) then you shouldn't reference the Shared project. The swagger claases is what you get/want then.
But you don't need Swagger in Blazor. The opportunity to share DTO classes in Shared is one of the highlights of Blazor.
If you want some help with the boilerplate stuff on the Client then there are options like refit. See this blog about it.

How can I build a OData client based on a shared model (POCO classes)?

In my project I am using OData v3 and v4 (ASP.NET Web API with Entity Framework in the back).
Currently I built a client using the Visual Studio tools.
But is there another way? Do I really have to build a client based on the $metadata and the toolset?
Is it possible to share my model (contract) by a shared library and build a client like this:
var client = new ODataClient<MySharedModel>(uri);
MySharedModel.Product product =
client.Products.Where(p => p.Category.Name == "Vegetables").FirstOrDefault();
The model can be a set of my own DTO objects which I can map to the equivalent entity framework objects.
My goal is, to share a well-documented model (source code XML documentation) with additional logic such as a ToString implementation and additional properties. Further more I save a additional step: generating a client (this sucks when you build and publish all your packages automatically on TFS Build server).
Is this possible for OData v3 or OData v4?
OData has recently started reviving and the team is regularly releasing new updates of the OData Connected Service entity generator, so you might want to consider giving it another shot.
You can definitely reuse the same model, but then you'd lose client-specific features that are generated for you, for example a dedicated container with all entity-sets as properties, collection properties exposed as ObservableCollection<T>, as well as self-tracking entities, as well as others.
All classes are generated as partial classes, so you can always extend them by adding methods into your own parts, which can, for this matter, also be shared classes.
Regarding the documentation, it's not supported at the moment, but this has been suggested and seems to be considered for future development.
Anyway, it's definitely possible, and shouldn't be to hard using your own entities.
To learn how to facilitate OData client access using your client POCOs, I'd recommend generating the model once and keep the code off your project or as excluded files, just for the reference, so you can mimic a similar functionality that works for you. That was the most helpful way to me.
Additionally, you will benefit from having a look at the documentation and the API reference docs, which has been a bit refreshed lately.

AutoRest from Swagger but reusing my existing assembly classes

I have a Windows UWP client application that needs to call a REST API hosted by my ASP.NET service. To generate my client proxy I use the following Visual Studio option...
Right click project -> Add -> REST API Client...
I provide the URL of the swagger endpoint and it generates the expected client code. But the downside is it generates all the classes even though in my case I have a shared class library that has all the server side classes defined. This is a pain because the generated classes do not respect the inheritance of my class hierarchy and flattens everything into non-inherited classes.
Is it possible to get AutoRest to reuse an existing .NET library for classes instead of always generating new classes? This was an option when I used the WCF client proxy generator.
It seems like Add REST API client doesn't have advanced setting for reusing. But Add REST API client has two ways for loading metadata file, swagger URL and existing metadata file. By testing on my site, it should be able to update an existing metadata file and to remove or adjust the nodes that you don't want be generated. And then load the updated existing metadata when adding REST API client.
The classes generated may be determined by the metadata json file and the host value. You may also try to submit a request here to see if swagger team can keep the hierarchy when generating the meta file. Or you may need to manual create the proxy to reuse the libraries.
I think it would be fair to describe the "REST API Client" generation tool in Visual Studio as "spartan".
This answer may be too late to help you, or there may be reasons why you can't use a different tool, but in the hope of benefiting you and/or future readers I'll detail how I achieved generating a REST client in NSwagStudio which reuses my existing classes and enums. (NSwagStudio is free and open source, and I have no affiliation).
On the left hand pane, we select our input. Besides the expected Swagger feeds there are some interesting options such as "Web API via reflection" which "uses .NET reflection to analyze ASP.NET Web API or ASP.NET Core controllers" - this is the option I used but my screenshot shows the default Swagger input.
On the right hand pane, click "CSharp Client" and switch to the "CSharp Client" tab.
The magic bullet is to untick "Generate DTO types":
This will cause it to generate only the client, so you can reuse your existing DTOs.
You'll want to specify a namespace for the client, and optionally one or more namespaces which will be added to the generated C# file as using directives. For example, if you want your client to be in the namespace MyNamespace and your model classes are in SomeOtherNamespace you'd enter the following:
It's well worth having a play with the options. A few quick notes about some of the defaults and why I'm happy with them:
The HttpClient is injected and you control the lifecycle (which seems to me a good thing)
A BaseUrl property is defined. I haven't tested this yet but I'm hopeful from looking at the generated code that this will allow me to safely spin up multiple instances of the client class to talk to multiple servers which share the same API
The JsonSerializerSettings property is protected, but can be configured via the UpdateJsonSerializerSettings partial method
I've saved my settings from the File menu and added the .nswag file to source control, so that I can easily regenerate the client in future if necessary.

service reference proxy class renamed

I'm having my Web Application which hosts Webservices (svc) which are used in a Silverlight Webapplication. After a while I added some new stuff to my Service and now I tried to refresh my proxy classes in the Silverlight Application Project.
Unfortunately, Visual Studio now generates new class names.
Before I had this:
public SilverlightApplication.ServiceReferenceDoc.Document Document
but now I get a different class name (number one behind the name)
SilverlightApplication.ServiceReferenceDoc.Document1 Document
Which is really bad because my Silverlight Projects have a lot webservices and these have a lot of code which uses these proxy classes.
So far I found out it generates the proxy class 2 times.
Some ideas why this renaming is happening? I already tried VS2015, VS2013 and also I deleted the complete reference and add it again, but it's the same.
We had mixed EF classes with own classes. That caused the generation of two classes with the same name.

Project structure for Schema First Service Development using WCF

I have WSDL and XSD as starting point. (WSDL is generated from XSD using WCSF Blue tool). From the WSDL, using a tool, the service code is generated. The project name is “Autogenerated_Service_Project”. Inside this project it will have [ServiceContract] and [DataContract] classes. It has a data contract named “EmployeeDataContract”. In the GetEmployee() service operation, this datacontract is returned to the client.
I have a business layer project named “Business_Project”. It has a method that returns “Employee” entity object.
At present, I am referring the “Business_Project” inside “Autogenerated_Service_Project”.
Business_Project.MyClass b = new Business_Project.MyClass();
EmployeeDataContract d = b.GetAssociate();
return EmployeeDataContract;
The challenge comes when there happens a change in WSDl. When the WSDL is the changed the “Autogenerated_Service_Project” will be recreated and the code mentioned above will be lost.
What is the solution to overcome this code lose?
Note: The “Autogenerated_Service_Project” is the top most project. Ideally, it cannot be referred by any other projects.
You may change the way calling Business layer(may your solution needs additional layer)
But in simple way, you can generate the proxy once, when changes happen to WSDL
handle the changes manually,Or use the tool only for new services.
If the services on WSDL are finely grained, the solution may be applicable.
This can be resolved by using Partial Classes in a different file. The code given in the question can be moved to this new partial class file. This file will persist even if the auto generated file is re-created.

Categories