I'm having a problem with excluding a specific DTO from Swagger in my ServiceStack application. Here's my setup:
[Route("/lists", "GET")]
public class GetLists : IReturn<GetListsResponse>
{
}
[Route("/lists", "POST")]
[Exclude(Feature.Metadata)]
public class CreateList : IReturn<CreateListResponse>
{
}
The behavior I'm expecting is the Swagger will remove the POST request docs but not the GET. Instead I'm getting both of them listed. Any help with what I'm doing wrong is appreciated.
UPDATE: I have tried adding the following attribute to no success:
[Restrict(VisibilityTo = RequestAttributes.None)]
The visibility of different Request DTO's should now be resolved from this commit that's available from v4.0.55 that's now available on MyGet.
From looking at the documentation, it looks like you can either exclude properties of a DTO or all services using a DTO -- but it doesn't say anything about excluding only certain verbs.
You can restrict Visibility using the [Restrict] attribute. (see documentation). This is a class based attribute and should be placed on your Service class. Visibility affects whether or not the service shows up on the public /metadata pages (& I am hoping for Swagger as well).
Have you tried the below?
[Route("/lists", "POST")]
[Restrict(VisibilityTo = RequestAttributes.None)]
public class CreateList : IReturn<CreateListResponse>
{
}
Related
I have a requirement where i need to weld a ContentPart to all the content types. Please guide me what is the best place to write this code.
I looked into the Orchard source code where InfosetPart is being welded with all content types in ContentHandlerBase's Activating method.
Following the InfosetPart weld mechanism i created one class inheriting from ContentHandlerBase and in Activating method i placed a break point with following condition which is getting hit again and again (more than once for one content type)
context.ContentType == "Page"
I'm not sure if it should be as it is because ideally it should hit this condition only once.
The way you are implementing it is correct. Your code is executed multiple times because content handlers are invoked for each content item, and not just for the content type. This also allows you to weld your part to only some of you content items, not all items of a specified type.
You wrote that you created a subclass of ContentHandlerBase. You should use ContentHandler as a base class.
Below is a simple code example how this should be done.
public class MyPartHandler : ContentHandler
{
protected override void Activating(ActivatingContentContext context) {
context.Builder.Weld<MyPart>();
}
}
I must be daft, but I cannot figure out what the usage of the [Api] attribute actually does for ServiceStack's SwaggerFeature.
Not tagging [Api] doesn't seem to influence whether or not the api shows up in Swagger and I cannot find a description rendered anywhere when using it like [Api("Service Description")]
My usage is like this:
[Api("Monkey Service Description")]
[Route("/zoo/monkey/{Id}", "GET", Summary = "Get MonkeyDocument by Id", Notes = "Returns a MonkeyDocument based on Id")]
public class GetMonkey : GetAnimal, IReturn<MonkeyDocument> // GetAnimal Has Id property
{
}
In Swagger-UI, the results show up on the page when expanded as:
/zoo Show/Hide List Operations Expand Operations Raw
+ GET /zoo/monkey/{Id} Get MonkeyDocument by Id
Implementation Notes
Returns a MonkeyDocument based on Id
ApiAttribute is no longer used in any Swagger-related functionality. The only usage of it I could find is related to the metadata page.
Your use of RouteAttribute to describe the service endpoint is the correct way to document your routes in Swagger. You can browse the source of SwaggerApiService and its unit ests to learn more about what attributes, etc., can be used to document your APIs in Swagger.
Edit
Actually, as mentioned in the comments, the ApiAttribute Description value is being returned to the Swagger UI client. e.g. the JSON sent back from the initial Resources request looks something like:
{
"swaggerVersion":"1.1",
"basePath":"http://localhost/api",
"apis":[
{"path":"/resource/zoo","description":"Monkey Service Description"}, ...
]
}
This particular description value is separate from the Route attribute description values, which are rendered in the Swagger UI and are returned from a separate Ajax request. The ApiAttribute description values, though they are returned to the Swagger UI client and stored in a SwaggerResource object in swagger.js, don't seem to be displayed on the screen in any way. At least with the current version of Swagger used by ServiceStack.
Here's a screen shot that shows how the Api and Route attributes are used on the Metadata page for a given DTO. I set up two Routes for the same DTO class to show the difference:
What I'm looking to do is have 2 views of an orchard page.
The first will include headers and footers, the second just the main body content.
The reason is so that we can maintain the body in one place, and it will be used either as a stand alone site, or just embedded within another.
I'm thinking that it would be done by accessing the page using a different route, or appending a querystring parameter.
Any other options are welcomed.
The method I am about to describe is arguably a hack and may go against some of the intentions of the creators of Orchard, but it will get the job done.
Orchard uses the ThemeFilter with the Themed attribute to decide whether the current controller action's output will be 'themed' --- i.e., be displayed with headers and footers. The controller used by Orchard to display content items has this attribute enabled, which is why content items are displayed themed. What you are asking to do is to suppress this 'themed' mode based on the presence of a query string parameter.
ThemeFilter kicks in at a very early stage of the page request and applies itself by setting a value in the current request's http context.
ThemeFilter.cs:
public static void Apply(RequestContext context) {
// the value isn't important
context.HttpContext.Items[typeof (ThemeFilter)] = null;
}
This class does not provide a way of unApplying this value. If you are willing to modify the Orchard source code, you may add this method yourself:
public static void Unapply(RequestContext context) {
context.HttpContext.Items.Remove(typeof (ThemeFilter));
}
Then you can simply create your own action filter that checks for the existence of a query string and then call this method if appropriate, something like:
using System.Web.Mvc;
using Orchard.Mvc.Filters;
using Orchard.Themes;
namespace Demo {
public class UnthemeFilter : FilterProvider, IActionFilter {
public void OnActionExecuting(ActionExecutingContext filterContext) {
}
public void OnActionExecuted(ActionExecutedContext filterContext) {
if (filterContext.RequestContext.HttpContext.Request["unthemed"] != null) {
ThemeFilter.Unapply(filterContext.RequestContext);
}
}
}
}
Now by adding ?unthemed=true, you will be able to suppress the theming.
If you are unwilling or unable to modify the Orchard source code, it is still possible to do the same thing by directly removing the typeof (ThemeFilter) from the HTTP context in your filter. However, this breaks encapsulation and should probably be avoided in object-oriented programming.
I am trying to get my head around ServiceStack self-hosted app and the new API.
Adding two views of the same name in separate folders results in an error at startup. Is this not allowed?
Foo\
Index.cshtml
Bar\
Index.cshtml
Is there a way to specify a template via a decorator on a method or directly as a return value? I know about the convention of naming views after DTOs. I prefer to be more explicit or follow a convention closer to Sinatra/Express.
return Render(typeof(Views.Foo.Index), new { Name = "Nelly" });
The ServiceStack's Razor Rockstars website which holds the documentation for Razor support in ServiceStack lists some options for selecting a different template:
If it doesn't follow the convention (i.e. Request or Response DTO name) then you can dynamically specify which view or layout template gets used by returning a decorated HttpResult like:
return new HttpResult(dto) {
View = {viewName},
Template = {layoutName},
};
If you're using a static view (i.e. service always uses the same view) then you can specify what view to use by decorating it with the [DefaultView] attribute
[DefaultView("Rockstars")]
public object Get(Rockstars request) {
...
return responseDto;
}
In either case, if you want it strong-typed you can use something like typeof(RequestDto).Name.
View names must be unique
Unlike MVC, heirachy's does not influence view selection in ServiceStack and because each View Page (i.e. razor pages in the /Views folder) must be unique, you're free to lay them out in any flat or nested folder structure you wish.
I am using Liferay 6 for development.
I have one query with respect to extending MVCPortlet class and providing the methods.
In some of the examples, during extending MVCPortlet and providing customized methods, is it mandatory to provide the parameters as ActionRequest and ActionResponse to the method as shown below:
public void addBook(ActionRequest request, ActionResponse response) {
}
So my question is, is this syntax mandatory?
Thanks in advance.
Yes, it's mandatory as this implements an action handler. You can also override GenericPortlet's processAction with the same parameters or use the #ProcessAction annotation, but in all cases you'll have to have a way to pass the actual request into the portlet. And that's what the parameters are for.
If you don't provide the parameters, the method will not be found by MVCPortlet's reflection-based resolving of the actual action name.