I am trying to use Swagger to document rest services created with ServiceStack 3.9.70...
This is the layout of the solution:
[Product.Services.Rest.dll]
AppHost.cs
//Tell Service Stack the name of your application and where to find your web services
public AppHost() : base("Product Services", typeof(Product1Service).Assembly) { }
[Product.Services.Rest.ServiceInterface.dll]
+-Services
+-Product1Service.cs
+-Product2Service.cs
+-Product3Service.cs
[Product.Services.Rest.ServiceModel.dll]
+-Operations
| +-Product1.cs
| +-Product2.cs
| +-Product3.cs
|
+-Types
+-Type1.cs
+-Type2.cs
+-Type3.cs
Using the swagger-ui, I have set discoveryUrl: "/resources"
When starting the swagger html, only the operations in one of the Product{n}.cs shows.
When running the /metadata all operations are shown.
Has this something with how I have structured the solution ?
Related
we have the following scenario with REST custom connectors.
I have followed the lb4 guidelines to create REST based custom connectors, let's say i have two connectors i.e secrets and hello-world.
I also have the loopback application which has data sources, models, repositories and services for 2 integrations.
But I want to maintain a single controller which has service injection in constructor like below
#inject(ConnectorServiceBindings.CONNECTOR_SERVICE) public externalDataService: ConnectorRepositoryService,
here ConnectorRepositoryService is an interface which has contract for method called getSomething(), so i have 2 services which implements interface for calling respective connector.
So in my application.ts i have this.bind(ConnectorServiceBindings.CONNECTOR_SERVICE).toClass( SecretsService, ); this to bind the injection with respective service.
But i needed to have a condition here to select the binding like below
if (type === "secrets") { // how to pass this type during runtime
this.bind(ConnectorServiceBindings.CONNECTOR_SERVICE).toClass(
SecretsManagerServiceService,
);
} else {
this.bind(ConnectorServiceBindings.CONNECTOR_SERVICE).toClass(
HelloWorldService,
);
}
is there a way we can do this binding whenever we get new API request?????
FYI : controller has single POST end point which internally calls interface method using this.externalDataService.getData?.()!;
Question 1 : Why do you want to bind at application.ts?
Ans : In future we want to add more connectors, so doesn't want to touch the controller code every time.
I have an application built from a series of web servers and microservices, perhaps 12 in all. I would like to monitor and, importantly, map this suite of services in Applications Insights. Some of the services are built with Dot Net framework 4.6 and deployed as Windows services using OWIN to receive and respond to requests.
In order to get the instrumentation working with OWIN I'm using the ApplicationInsights.OwinExtensions package. I'm using a single instrumentation key across all my services.
When I look at my Applications Insights Application Map, it appears that all the services that I've instrumented are grouped into a single "application", with a few "links" to outside dependencies. I do not seem to be able to produce the "Composite Application Map" the existence of which is suggested here: https://learn.microsoft.com/en-us/azure/application-insights/app-insights-app-map.
I'm assuming that this is because I have not set a different "RoleName" for each of my services. Unfortunately, I cannot find any documentation that describes how to do so. My map looks as follow, but the big circle in the middle is actually several different microservices:
I do see that the OwinExtensions package offers the ability to customize some aspects of the telemetry reported but, without a deep knowledge of the internal structure of App Insights telemetry, I can't figure out whether it allows the RoleName to be set and, if so, how to accomplish this. Here's what I've tried so far:
appBuilder.UseApplicationInsights(
new RequestTrackingConfiguration
{
GetAdditionalContextProperties =
ctx =>
Task.FromResult(
new [] { new KeyValuePair<string, string>("cloud_RoleName", ServiceConfiguration.SERVICE_NAME) }.AsEnumerable()
)
}
);
Can anyone tell me how, in this context, I can instruct App Insights to collect telemetry which will cause a Composite Application Map to be built?
The following is the overall doc about TelemetryInitializer which is exactly what you want to set additional properties to the collected telemetry - in this case set Cloud Rolename to enable application map.
https://learn.microsoft.com/en-us/azure/application-insights/app-insights-api-filtering-sampling#add-properties-itelemetryinitializer
Your telemetry initializer code would be something along the following lines...
public void Initialize(ITelemetry telemetry)
{
if (string.IsNullOrEmpty(telemetry.Context.Cloud.RoleName))
{
// set role name correctly here.
telemetry.Context.Cloud.RoleName = "RoleName";
}
}
Please try this and see if this helps.
I noticed that App Insights has a field called appName (and appId) when querying in the analytics tool (see below), however I don't see a way of setting this in the client library. Can this be set?
I'm trying to log related items to app insights, though the log source may be different. Using that field seems like a nice way to handle that scenario, though I'm open to different scenarios.
There is a preview where you can set the application name. This is done in the following way:
enable the preview Application Map
set the ITelemetry.Context.Cloud.RoleName (this is the application name)
Enable preview: Go to the portal -> the application insights -> previews -> Enable Multi-role Application Map
Set the application name:
This is done by adding an interceptor:
public class ServiceNameInitializer : ITelemetryInitializer
{
public void Initialize(ITelemetry telemetry)
{
telemetry.Context.Cloud.RoleName = "MyProcessName";
// RoleInstance property modifies the app name in the telmetry dashboard
telemetry.Context.Cloud.RoleInstance = "MyAppInstanceName";
}
}
Add the interceptor to the application insights configuration in startup.cs:
private void ConfigureAppInsights(IServiceCollection services)
{
services.AddApplicationInsightsTelemetry(Configuration);
TelemetryConfiguration.Active.TelemetryInitializers
.Add(new ServiceNameInitializer());
}
Read more at: cross-process-application-insights-with-multi-role-application-map
Those values are populated in the backend and specify Application Insights resource details and thus cannot be changed.
What your're looking for is custom dimensions.
For example, to send the telemetry:
EventTelemetry telemetry = new EventTelemetry("my custom event");
telemetry.Properties.Add("MyApp", "HelloWorld");
telemetryClient.TrackEvent(telemetry);
To query those custom dimensions:
customEvents
| where customDimensions['MyApp'] == "HelloWorld"
I'm looking to demonstrate ServiceStack to my team, and as part of the demo I want to create some documentation. The UseCases.SwaggerHelloWorld runs fine, but my project (which has 1 functioning service) returns an empty swagger page. When I visit /resources it returns:
{
"swaggerVersion":"1.2",
"apis":[],
"apiVersion":"1.0",
"basePath":"http://localhost:29672",
"info":{"title":"Reports.Api"}
}
I then copied the Hello* service and models into my API project (in the same assembly as the host) and this worked. I then moved the service and models out into separate projects and the docs disappeared again.
So my question is, how can you document APIs when the models are in a separate DLL? The project structure is the same as recommended when you create a solution using the servicestack solution template.
The AppHost constructor tells ServiceStack which assemblies it should scan to locate, register and auto-wire your Services, e.g:
public class AppHost : AppHostBase
{
public AppHost() : base("Hello App", typeof(HelloService).Assembly) {}
}
It supports specifying multiple Assemblies if your Services are maintained in different projects, e.g:
public class AppHost : AppHostBase
{
public AppHost() : base("Hello App",
typeof(HelloService).Assembly, typeof(OtherService).Assembly) {}
}
The Modularizing Services docs has more info.
The DTO's used by the Service can be in a different project, you just need to specify which assemblies the Services are in. Although it's recommended the DTO's are maintained in a separate dep-free project which is the recommended Physical Project Structure that's contained in each ServiceStackVS VS.NET Project Template.
Using the first example in the ServiceStack Auto Query documentation in a project structured similar to the EmailContacts sample project (i.e. separate projects for the ServiceModel and ServiceInterface), how would one register the custom route "/movies" defined by the Route attribute?
[Route("/movies")]
public class FindMovies : QueryBase<Movie>
{
public string[] Ratings { get; set; }
}
Normally, custom routes such as these can be register by passing the ServiceInterface assembly when instantiating AppHostBase:
public AppHost() : base("Email Contact Services", typeof(ContactsServices).Assembly) {}
However, the FindMovies request DTO does not have an associated service and therefore won't be included. No routes are registered.
If I pass typeof(FindMovies).Assembly instead of or in addition to typeof(ContactsServices).Assembly, then the pre-defined route will be registered (i.e. shows up in the metadata, postman, etc.) but the custom route is still not registered (i.e. does not show up in the metadata, postman, etc.).
What is the best way to register the custom route using attributes when there is no service and the ServiceModel and ServiceInterface are in separate projects?
These issues should be resolved in v4.0.24+ that's now available on MyGet.
There's a new AutoQueryFeature.LoadFromAssemblies property to specify an additional list of assemblies to scan for IQuery Request DTO's. This automatically looks in the assemblies where your other Request DTO's are defined so in most cases nothing needs to be done as it will automatically be able to find your query services.
The routes for Query DTO's should now appear on the metadata pages as well as Swagger and Postman metadata API's.