ServiceStack + Swagger-UI [Api] Attribute Usage - servicestack

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:

Related

how to access b2c sign in elements using javascript for UI customizing

i want to access b2c sign in page's h2, email and password elements to customize them.
using document.getElementsByClassName not giving any result
B2C injects it the html inside the predefined div with id api (<div id="api>). You can read more on this here. Now inorder to access the html elements injected by B2C inside the api div, you might have to check the structure of the html elements in the developer tools initially, and then try to select the specific element using javascript.
For eg: When B2C injects the html elements inside the api div, the section that contains the input tag for email looks like:
Now if you see, the input tag for email, doesn't contain any class there, rather if you check closely, you will find that each input element like for email or password is encapsulated under a parent div with class "entry-item". So in that case, the document.getElementByClassName would work on that level.
So to conclude, first identity the element you want to select using javascript using the dev tools on the browser, and then write the javascript accordingly.
In case the element you find doesn't contain any id or class, you can always use document.querySelector and select the tag to perform DOM manipulations.
Let me know if this works or if there are more queries around this.

ServiceStack Swagger DTO won't Exclude

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>
{
}

How to render a template by name?

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.

ASP.NET MVC 2 JQuery POST not displaying the model state errors

I have been using asp.net mvc for a bit (but I'm still a beginer). I want to have the ability to update two views as a result of a jquery postback.
Basically I have a list and a details view. The details view is presented using a jquery popup (using jquery-UI popup). I only want to update the list if the details save is successful (i.e. there are no validation errors on the details view). However, if there are any validation errros in the details view, I want to update the details view so that the user sees the validation errors.
so I thought in my controller, I return a JsonResult instead of a View.
[HttpPost]
public ActionResult SavePersonInfo(Person p) {
if(ModelState.Valid) {
return View("PersonList");
}
return Json({Error = true, View = PartialView("PersonDetails", p)});
}
As you can see if there are no errors I return the person list view, but if there are any validation errors, I have return the details view. The reason that I'm returning a JsonResult is I need to tell my view there is an error so that the view (jquery) knows which section to update (as in whether to update the person list 'div' or the popup dialog 'div').
So, in my view, the jquery is as follows (please assume that there is a form for entering in the person details and "SubmitPersonForm();" function is called upon clicking on the "Save" button):
<script type="text/javascript>
$('#btnSave').click(function (event) {
onBegin();
$.ajax(
{
type: "POST",
url: "/Person/Save",
data: $('form').serialize(),
success: function (result) {
if(result.Error) {
$('#dvDetails').html($(result).View));
}
else {
$('#dvPersonList').html($result);
}
}
});
});
</script>
So the problem that I have now, is that when there is a validation error, I do see the correct, 'div' being updated, but I lose the asp.net mvc validation messages. I do not see any validation errors in red, as if ASP.NET MVC is completely ignored them. However, my ModelState does have those errros, just not displayed in the details view. I do have valication summary and Html.ValidationFor(m => ...) statements put in my details view.
Could someone tell me why I'm not seeing the validation errors? although I'm using a JSonResult, I do use the right property which is a valid view when I render the 'dvDetails'. Am I doing something that I'm not suppose to in asp.net mvc? Btw I'm using asp.net mvc2 RC with Visual Studio 2010 RC.
Thank you.
The Url does not match the Action name ... not sure if you maybe are calling the wrong Method on the controller ... just an idea. :-)
ASP.NET MVC code processes the response to display validation errors stored in the ModelState during a postback. Because you are using an Ajax Post, the postback code is not rebuilding the page and displaying the validation errors. If you want to display validation errors, you have to handle it yourself.
I've done it by passing the ModelState errors as an array in the response. I process my Ajax response to update the validation error placeholder elements in the form with corresponding error messages in the response.
A warning, though: the keys in the ModelState may have their case changed, so an element ID string in the form doesn't exactly match the string that's used for the key. ModelStateDictionary is case-insensitive, but DOM ID's are not.

yui, form submission and data table

I'm a Java programmer, but not a JavaScript programmer. I have just discovered YUI, and am trying to get started using it. What I'd like to try and do is have the query form at the top of the page, the user press Submit and the results show up in a YUI DataTable below the query form.
Normally, of course, on a HTML form the user presses Submit, the request gets sent to the server, and I use Struts to process it and then forward the request to a JSP and HTML gets sent back to the browser. That's what I do on a daily basis. With Ajax, I understand it's different in that I should return XML instead. Not a problem. Easy to do.
The questions I have deal with the YUI side of things. When the Submit button is pressed, what happens? Not normal form submission, right? Do I implement an onSubmit() JavaScript function which then triggers some YUI DataSource to go fetch the data? How do the request params get passed? Hopefully I don't have to construct the request manually. I'm guessing that I use a YAHOO.util.XHRDataSource and that's the DataSource for the DataTable.
I've managed to get the YUI DataTable to work using an HTML table element. Now I just need to switch it over to real data. Curiously, the YUI documentation seems a bit weak here, unless I'm missing something. Maybe this is just basic Ajax that the YUI docs don't cover?
First of all, when working with Ajax you don't need to return XML from the server, you could return plain text, XML, JSON strings, literally any form of textual data that you want. One example of populating a Datatable with JSON data is provided here:
http://developer.yahoo.com/yui/examples/datatable/dt_xhrjson.html
An example of how to send a post request using Ajax and YUI is provided here.
http://developer.yahoo.com/yui/examples/connection/post.html
That should get you started, now just link both of them together.
To connect to the server you can use the Yahoo.util.Connect.asyncRequest method which takes in the following parameters:
static object asyncRequest ( method , uri , callback , postData );
See an example here, this one uses "GET" so you can use either "GET" or "POST" just make sure you pass in your parameters
http://developer.yahoo.com/yui/examples/json/json_connect.html
Once your function returns on your "onSuccess" do the following to parse the response text to JSON
try {
jsonData = YAHOO.lang.JSON.parse(o.responseText);
}
catch (x) {
alert("JSON Parse failed!");
return;
}
The "jsonData" object now contains your data, so now you can follow this example:
http://developer.yahoo.com/yui/examples/datatable/dt_basic.html
It shows you how to initialize a datatable with a local object holding the datasource. basically it would be something like this
var myColumnDefs = [
{key:"Column1Data", label:"Column1 Header" sortable:true, resizeable:true},
{key:"Column2Data", label:"Column2 Header" sortable:true, resizeable:true}
];
var myDataSource = new YAHOO.util.DataSource(jsonData);
myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;
myDataSource.responseSchema = {
fields: ["Column1Data","Column2Data"]
};
var myDataTable = new YAHOO.widget.DataTable("basic",
myColumnDefs, myDataSource, {caption:"DataTable Caption"});
For this to work, you have to have a "div" container in the HTML code with an id of "basic" note this matches the first parameter on the DataTable
Hope this helps

Resources