How to format/style ///<summary> in Web API 2 - c#

Maybe this isn't even possible, but it seems silly that I can't figure it out (nor can find anything conclusive after searching).
With a MVC/C# Web API 2 project, your controllers can be documented using something like:
///<summary>
///This is something really cool that you should use. I want <b>this bold</b>.
///</summary>
[HttpPost]
public MyResponse MyMethod(SomeInput input)
{
....
}
When the API runs, the project automatically builds the help site, and I can see the above endpoint/method, and its description ( text), but I've head to figure out how to do any sort of styling to the summary. It appears that the HTML tags get striped from the help page's output. Notice in my example above, I have "this bold". I'm not so much concerned about bold, but more interested in being able to use unordered lists () and other basic HTML tags to just do some real basic formatting.
Is this even possible?
Is there a trick to it?
Is there some other markup/formatting I should be using?
Note - The actual endpoint that I'm trying to document at moment, happens to be a mime multipart form, and the framework won't document those out of the box. To get around this, I've created some helper methods in HelpPageConfigurationExtensions (to determine if the current endpoint view is one that requires custom documentation), in HelpPageApiModel.cshtml to determine if it should show the stock documentation or the custom docs, a helper library that contains the custom doc information, and a series of help functions that use some reflection to rapidly build HTML tables for the rest of the help page's documentation (e.g. the request and response objs). I'm mentioning this because maybe I just need to further extend my custom doc library to include (hard code) the value, and then in the view I can just #Html.Raw it -- opposed to trying to get the actual method's to output with formatting.
Thoughts?
Thanks!

Related

How to configure swagger to make complex [FromUri] GET parameters show up nicely in Swagger

I've been trying to figure this out for about a week now. It's time to ask S.O.
I have 4 overall goals here:
The controller code needs to use ViewModel request inputs for validation reasons. (Controller Snippet)
Client code for my API should use a nice model syntax. (Client Code Snippet)
For the swagger UI page, I would like the "Try me" interface to be usable. Either a bunch of text boxes, or a text area for a json blob to serialize and send over.
GET request
Client Code Snippet:
var response = client.GetUserProductHistory(new Models.UserProductHistoryRequest() {
Locale = "en-US",
UserPuid = "FooBar"
});
Controller Snippet
[HttpGet]
[HasPermission(Permissions.CanViewUserProductHistory)]
public JsonPayload<UserProductHistoryResponse> GetUserProductHistory([FromUri]UserProductHistoryRequest model)
{
JsonPayload<UserProductHistoryResponse> output = new JsonPayload<UserProductHistoryResponse>();
return output;
}
I have tried using [FromBody]. It looks great, but I get an error that says 'GET requests do not support FromBody'.
I tried using [FromUri], but then the generated client gives me like 15 method parameters per call in the generated client.
I tried using [FromUri], and operation filters so that the parameters would be condensed into Ref parameters (complex objects as defined by the spec). This actually worked decently for the client generation and the server side. Problem is, the UI for swagger looks really lame. A single TEXT box that you can't actually use very well. If I can figure out how to get the Swagger UI to change the appearance of the [FromUri] request to more closely match the [FromBody] UI, I will be in good shape here. Any ideas or pre-existing content that would point me in the right direction here?
Swagger is not the limitation - REST itself is. By definition of REST, web servers should ignore the incoming request body on all HTTP GET methods. ASP.NET enforces this convention, which is why you it doesn't allow you to use [FromBody] on the GET method.
When designing a REST API, the better practice is to use POST methods for an actual search. This will allow to use [FromBody], and as a bonus, Swagger will behave the way you want it to. See here for a supporting opinion: https://stackoverflow.com/a/18933902/66101

Url Encoding an array

This might seem dirty but it's for documentation purposes I swear!
I am accessing my services using GETs in my documentation so people can try things out without needing to get too complicated.
Appending x-http-method-override=POST to the URL forces the server to take a GET as a POST
This is all good except when I need to POST an array of objects. This would be simple in a standard POST but today I have a new bread of nightmare.
The expected POST looks like:
{"name":"String","slug":"String","start":"String","end":"String","id":"String","artists":[{"id":"String","name":"String","slug":"String"}],"locationId":"String"}
As you can see there is an array of artists up in here.
I have tried to do the following:
model/listing?start=10:10&end=12:30&artists[0].name=wayne&artists[0].id=artists-289&locationid=locations-641&x-http-method-override=POST
But to no avail.
How can I get an array of objects into a URL so that service stack will be happy with it?!
I appreciate this is not the done thing but it's making explaining my end points infinitely easier with clickable example URLs
You can use JSV to encode complex objects in the URL. This should work for your DTO:
model/listing?name=wayne&artists=[{id:artists-289,name:sample1},{id:artists-290,name:sample2}]&locationId=locations-641
You can programmatically create JSV from an arbitrary object using the ToJsv extension method in ServiceStack.Text.

Orchard client-side validation - how SHOULD it look/work?

I'm attempting to use client-side validation in an admin page in Orchard. I've been successful at making it work using the techniques discussed in this question, but after doing some digging in the Orchard source and online, it seems to me that commenting out these lines
// Register localized data annotations
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new LocalizedModelValidatorProvider());
is subverting some built-in Orchard functionality which allows for localized error strings. At this point, either having these lines in our out of OrchardStarter.cs is the only difference between validation working and not working for me.
What I'm hoping for is some guidance on this, maybe from the Orchard team. If these lines have to be out in order for validation to work, why are they there in the first place? If they are there for a good reason, what am I (and others) doing wrong in our attempts to get client-side validation working? I'm happy to post code samples if needs be, although it's a pretty standard ViewModel with data annotations. Thanks.
The lines are there to replace the DataAnnotationsModelValidatorProvider (DAMVP) with Orchard's own implementation, which allows localizing the validation messages the Orchard way. The way it does this is by replacing e.g. [Required] with [LocalizedRequired] before passing control on to the DAMVP. Note that DAMVP does get to do its job - but only after Orchard has "messed" with the attributes.
The problem is that DAMVP uses the type of the Attribute to apply client validation attributes. And now it won't find e.g. RequiredAttribute, because it's been replaced by LocalizedRequiredAttribute. So it won't know what - if any - client validation attributes it should add.
So, out-commenting the lines will make you lose Orchard's localization. Leaving them in will make you lose client validation.
One workaround that might work (haven't looked enough through Orchard's code, and haven't the means to test at the moment) would be to make DAMVP aware of Orchard's Localized attributes and what to do with them.
DAMVP has a static RegisterAdapter() method for the purpose of adding new client rules for attributes. It takes the type of the attribute and the type of the Client-side adapter (the class that takes care of adding client attributes) to use.
So, something like the following might work:
In OrchardStarter.cs:
// Leave the LocalizedModelValidatorProvider lines uncommented/intact
// These are the four attributes Orchard replaces. Register the standard
// client adapters for them:
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(LocalizedRegularExpressionAttribute),
typeof(RegularExpressionAttributeAdapter)
);
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(LocalizedRequiredAttribute),
typeof(RequiredAttributeAdapter)
);
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(LocalizedRangeAttribute),
typeof(RangeAttributeAdapter)
);
DataAnnotationsModelValidatorProvider.RegisterAdapter(
typeof(LocalizedStringLengthAttribute),
typeof(StringLengthAttributeAdapter)
);
As for the official word, it would seem this hasn't worked since localized validation was introduced in 1.3, and the impact is considered low: http://orchard.codeplex.com/workitem/18269
So, at the moment, it appears the official answer to the question title is, "it shouldn't".

Parsing a Auto-Generated .NET Date Object with Javascript/JQuery

There are some posts on this, but not an answer to this specific question.
The server is returning this: "/Date(1304146800000)/"
I would like to not change the server-side code at all and instead parse the date that is included in the .Net generated JSON object. This doesn't seem that hard because it looks like it is almost there. Yet there doesn't seem to be a quick fix, at least in these forums.
From previous posts it sounds like this can be done using REGEX but REGEX and I are old enemies that coldly stare at each other across the bar.
Is this the only way? If so, can someone point me to a REGEX reference that is appropriate to this task?
Regards,
Guido
The link from Robert is good, but we should strive to answer the question here, not to just post links.
Here's a quick function that does what you need. http://jsfiddle.net/Aaa6r/
function deserializeDotNetDate(dateStr) {
var matches = /\/Date\((\d*)\)\//.exec(dateStr);
if(!matches) {
return null;
}
return new Date( parseInt( matches[1] ) );
}
deserializeDotNetDate("/Date(1304146800000)/");
Since you're using jQuery I've extended its $.parseJSON() functionality so it's able to do this conversion for you automatically and transparently.
It doesn't convert only .net dates but ISO dates as well. ISO dates are supported by native JSON converters in all major browsers but they work only one way because JSON spec doesn't support date data type.
Read all the details (don't want to copy blog post content here because it would be too much) in my blog post and get the code as well. The idea is still the same: change jQuery's default $.parseJSON() behaviour so it can detect .Net and ISO dates and converts them automatically when parsing JSON data. This way you don't have to traverse your parsed objects and convert dates manually.
How it's used?
$.parseJSON(yourJSONstring, true);
See the additional variable? This makes sure that all your existing code works as expected without any change. But if you do provide the additional parameter and set it to true it will detect dates and convert them accordingly.
Why is this solution better than manual conversion? (suggested by Juan)
Because you lower the risk of human factor of forgetting to convert some variable in your object tree (objects can be deep and wide)
Because your code is in development and if you change some server-side part that returns JSON to the client (rename variables, add new ones, remove existing etc.), you have to think of these manual conversions on the client side as well. If you do it automatically you don't have to think (or do anything) about it.
Two top reasons from the top of my head.
When overriding jQuery functionality feels wrong
When you don't want to actually override existing $.parseJSON() functionality you can minimally change the code and rename the extension to $.parseJSONwithdates() and then always use your own function when parsing JSON. But you may have a problem when you set your Ajax calls to dataType: "json" which automatically calls the original parser. If you use this setting you will have to override jQuery's existing functionality.
The good thing is also that you don't change the original jQuery library code file. You put this extension in a separate file and use it at your own will. Some pages may use it, others may not. But it's wise to use it everywhere otherwise you have the same problem of human factor with forgetting to include the extension. Just include your extension in some global Javascript file (or master page/template) you may be using.

interesting news article/blog post scraping problem

i need to scrape the text of blog posts to build a summary description of the blog posts similar to what techmeme.com does. not a problem when it's one or a handful of blog posts. however, the possible blogs from which to scrape the text is variable and unlimited. how would you go about doing this?
i've used the html agility pack and yql in the past, but there's nothing built-in either of those solutions to handle this requirement.
one thought i had was to search for div ids and div attributes named things like content, post, article etc and see how that worked - not really leaning this direction. the other idea was to search for the biggest text node in the html document and assume that's the node i want - could lead to some false positives. the final idea was to endeavor to create a crowdsourced data repository on google apps that would allow for the community to manage (read: create, update, delete) the xpath mappings for most of the popular news/blog platforms then you could query this list by domain or blog platform type and get the requisite xpath - but this seems like a hella undertaking.
of course, i know some of you have ideas that will work better than any of my hare-brained ideas.
what are your thoughts?
The only sure-fire way of doing this is to have a class for each blog. That way you can do what you need in the implementation of each specific class for each specific blog.
So you'll have an abstract base class that processes a blog and returns the data/info you need from a blog.
for example
public abstract class BlogProcessor
{
public abstract BlogResult ProcessBlog(string url);
}
Where BlogResult is a type you define that has all the information you'll need from a blog such as title, date, tags, post etc.
Each descendant knows how to extract this information for the blog is is specialized for.
If you call code you'll treat these descendant classes pollymorphic-ally like so:
foreach(var url in BlogsToParse)
{
var blogProcessor = BlogProcessorFactory.CreateInstance(url);
var blogResult = blogProcessor.ProcessBlog(url);
/* Do Something with blogResult */
}
Does that make sense?
In the implementation of each "ProcessBlog" method you could use HtmlAgilityPack to do the specific parsing.

Categories

Resources