NServiceBus Routing not working based on Assembly for generic types - .net-core

I have a scenario where I am sending a generic Command like: AddRequest.
When I configure routing using Assembly, it doesn't work (error: no destination specified):
routeSettings.RouteToEndpoint(assembly, "App2.Endpoint");
However the command gets sent successfully when configuring routing via type:
var genericType = Type.GetType("SharedApp.AddRequest`1[[SharedApp,MyObject]],SharedApp");
routeSettings.RouteToEndpoint(genericType, "App2.Endpoint");
Is something wrong/missing while configuring it via assembly ?

When NServiceBus scans the assembly it looks for message types but all it finds is an open generic type AddRequest<T>.When you send a message, you send an instance of AddRequest<MyObject> which is a closed generic type, so different from the one discovered.
Unfortunately NServiceBus routing system is not aware of generic types and uses type equality to determine the route. Because of that it does not know where to sent AddRequest<MyObject>.
The reason why NServiceBus routing system has been designed this way is it already uses one mechanism for group route registration which is based on assembly and namespace. You can register one route for a set of types provided they are defined in same assembly and/or namespace. If you introduced yet another mechanism for grouping e.g. based on generic types or based on type inheritance (i.e. route for base type is used for derived types) we would end up in a situation where a type can have multiple routes associated with no clear way to pick one over the others.

Related

Does a call to MapRazorPages() constitute a call to UseEndpoints()?

According to the documentation for UseRouting(), we must call UseEndpoints() afterward:
A call to UseRouting(IApplicationBuilder) must be followed by a call to UseEndpoints(IApplicationBuilder, Action) for the same IApplicationBuilder instance.
But in some code samples (e.g. here) I see UseRouting() calls with UseEndpoints() omitted and MapRazorPages() used instead. Is this safe?
I entered this query into ChatGPT:
What is the difference between App.MapRazorPages and App.UseEndpoints(Sub(Routes) Routes.MapRazorPages)?
...and it returned this helpful answer:
App.MapRazorPages is a method that configures the routing for Razor pages in an ASP.NET Core application. It adds a default route for all Razor pages, which is {page}/{handler?}, where page is the name of the Razor page and handler is the name of an optional handler method defined within the page.
App.UseEndpoints is a method that enables you to specify a pipeline of middleware that will be executed when a request is received by the application. Within the lambda expression provided to UseEndpoints, you can call MapRazorPages to add a route for Razor pages to the pipeline.
So, in short, App.MapRazorPages is a specific method that configures routing for razor pages, while App.UseEndpoints is a more general method that allows you to specify a pipeline of middleware and register various types of endpoints, including razor pages, in the application.
All well and good. Very nice. But what about the admonition from the documentation, that we must call UseEndpoints() at some point after we call UseRouting()? Is it safe to rely on only a call to MapRazorPages() to fulfill that requirement?
This answer seems to indicate so, but I'd like to make sure before I go stringing things together that I don't fully understand.
---EDIT---
Well, go figure.
I consulted the almighty ChatGPT on this one (should've done that at first, I guess) and he boomed down:
No, it is not safe to rely on a call to MapRazorPages() as a substitute for the required call to UseEndpoints().
UseRouting() is used to enable routing in an ASP.NET Core application. It sets up the routing system and prepares the app to handle incoming requests.
MapRazorPages() is an extension method that can be used to configure Razor pages in an ASP.NET Core application. It adds a Razor pages endpoint to the application's endpoint routing table, which allows the app to handle requests for Razor pages.
UseEndpoints() is used to define the endpoints for an ASP.NET Core application. It adds a route to the application's endpoint routing table for each endpoint defined within the lambda passed to it.
So, while MapRazorPages() can be used to configure razor pages and add a corresponding endpoint to the application's endpoint routing table, it cannot be used as a substitute for UseEndpoints(). UseEndpoints() is required to properly define the endpoints for an ASP.NET Core application and handle incoming requests.
So there we have it. But should we trust it? I'm a little bit wary, perhaps because I tend to prefer to live on the edge and not allow myself to be lulled into complacency by The Matrix.
Can someone corroborate?
It differs in different .NET versions.
For example, in .NET 5, you have to call app.UseEndpoints() to register routing. However, in .NET 6 you can register routes with a call to app.MapRazorPage() directly, leaving out both app.UseRouting() and app.UseEndpoints(). This is documented here.
Apps typically don't need to call UseRouting or UseEndpoints. WebApplicationBuilder configures a middleware pipeline that wraps middleware added in Program.cs with UseRouting and UseEndpoints. However, apps can change the order in which UseRouting and UseEndpoints run by calling these methods explicitly.

Web Services Model

I have 1 Site (MySite.com) / 1 Web Service (WebService.MySite.Com) and one Common Library (LibCommon)
The common Library Contains a Model e.g. UserModel = LibCommon.UserModel
The web service has a method 'Void CheckUser(LibCommon.UserModel model)'
However when I add the 'WebService' reference to 'MySite.com' the method changes so that it looks like 'Void CheckUser(WebService.MySite.Com.UserModel model)'
So I think fair enough I can just cast one object to the other as they are identical however .NET Says I cannot do this?
Is there a work around for this?
Cheers,
Note this is for WCF, and not ASMX web services:
You can't directly cast the original data class to the proxied class generated by the WCF service reference wizard. However, you can reuse the original data class in the client:
Add the library reference containing the transfer objects (i.e. LibCommon) as a reference to both the Service (WebService) and the Client (Mysite.com). When adding the service reference on the client, choose the advanced tab and then select Reuse types in referenced assemblies. This will then reuse the common data transfer classes, instead of duplicating the types with proxies.
Note however that by eliminating the proxied data class, you are introducing direct coupling between client and server - you should do this only if you have control over both client and server w.r.t. version control issues etc (e.g. able to deploy new versions of both client and server simultaneously)
As an aside, it is also possible to eliminate the shared service interface as well, by moving the server side Service contract interface into a separate, common assembly and then using a technique such as this or this.

What happens if web services changes the parameters?

Say i'm having a web service that accepts two arguments and that is being called/consume in my application. Now after some time, the web service changes and accepts three arguments, hence in my application, would that be throwing an error, or i need to just update the web reference, or i need to recreate a web serivce or would that be working fine?
Let me know if any doubts
Thanks!
You could add optional parameters where if a parameter value isn't given to the method a default value is used.
From a "pure" architectural aspect, you should never change the signature of a method of a service once it's in use. You should version by creating a new method with a different namespace. But staying pure is sometimes difficult to do.
In your case you need to update the Web reference in the client application and then modify the code to pass in the appropriate parameter to the method in the service proxy.

Service Reference Proxy method Generation

I have two Biztalk applications, each of which expose a webservice port,
I'm consuming them in an ASP.NET client using the 'Add service reference' tool from within the VS2010 GUI to generate the proxies.
But the proxy interface is slightly different in both. One takes two parameters, returns the 'response' via a parameter using the out keyword and has a void return type,
the other takes one parameter and returns the response using a typed return value.
I'm confused as to what is causing the difference in behavior, is something I'm doing as part of the creation of the references (as far as I can tell I've used the same process) or is it something about the server/WSDL I'm consuming?
EDIT -As per Grahams comment the type of proxy interface generated seems to depend on whether there is a namespace or not. I'll give the answer to whoever can put together the clearest description of what exactly is happening there.
As noted in the comments, the inclusing of a namespace in one of the services is what was triggering the difference in the proxy code generation. It's still not clear exactly why this is the case however.

Calling Web Service with primitive types within Orchestration - Can't map request message

I'm running into this problem when trying to call a SOAP Web Service from within a Biztalk orchestration.
The Web Service is an abapi exposed by SAP as a SOAP Web Service, and the signature of the web method I want to call is something like this:
Operation(param1 as System.String, param2 as System.String, param3 ArrayOfSomeClass)
When I see the schemas generated I noticed that only 'ArrayOfSomeClass' and 'SomeClass' were generated. But I don't see any schema that represents the whole request.
I also noticed that a web port type was generated, and the request message is represented as a multi-part message. The parts of this message contains all the scalar parameters (param1, param2) and also the array.
I know I can just use the assignment shape and fill the message by code, but this is not what I want because I would like to map another message to the web service request.
Is this possible? Any one had a similar issue?
Thanks in advance!
You observation is correct, schemas won't be generated for simple types and its clearly documented here and explains how you should work with such types.
http://msdn.microsoft.com/en-us/library/aa561724(BTS.20).aspx
XSD will not contain nodes for simple parameter types
When you add a Web reference and the Web method has a parameter that is a simple type, the generated XSD will not contain nodes for that parameter. Instead, the multipart message that is generated will contain a part that is of the simple type. The orchestration should handle this message part appropriately. If it is a part of the request to the Web service, manually assign the value to that part with a message assignment shape. If it is a part of the response from the Web service, manually access that part in an expression shape to see the value.
I didn't get your second point
I would like to map another message to
the web service request.

Resources