WebApi HelpPage HttpResponseMessage SetActualResponseType - asp.net-mvc-4

I am using the WebApi Help pages within an MVC4 project.
As per the following link, http://blogs.msdn.com/b/yaohuang1/archive/2012/10/13/asp-net-web-api-help-page-part-2-providing-custom-samples-on-the-help-page.aspx I have been setting the HelpPageConfig to set actual response types.
I have a controller that has two get methods on it
/// <summary>
/// Get the list of plans for a specified portfolio
/// </summary>
/// <param name="portfolioIdentifier">Portfolio Identifier (guid)</param>
/// <returns>
/// Returns a list of <see cref="RestDTOs.Plan"/> Plan objects
/// </returns>
public HttpResponseMessage Get(Guid portfolioIdentifier)
{
}
/// <summary>
/// Get full plan details.
/// </summary>
/// <param name="planIdentifier">Plan Identifier (guid)</param>
/// <returns>
/// Returns the <see cref="RestDTOs.Plan"/> Plan object
/// </returns>
[HttpGet]
public HttpResponseMessage Detail(Guid planIdentifier)
{
}
Within HelpPageConfig.cs i have added the following to try and set an example ResponseBody format
config.SetActualResponseType(typeof(Plan), "Plan", "GET");
This is working great on the Get method, but is not producing anything on the Detail method
What do I need to add to the HelpPageConfig so that the web api help will pick up and produce samples for the Detail method

MVC 5 has a built in attribute to set the response type.
More information here:
http://thesoftwaredudeblog.wordpress.com/2014/01/05/webapi-2-helppage-using-responsetype-attribute-instead-of-setactualresponsetype/
Just use:
ResponseType(typeof([Your_Class]))]

Try config.SetActualResponseType(typeof(Plan), "Plan", "Detail");...the second parameter here is expecting an action name...I see you are using Web API 1, so just FYI...in Web API 2, there is an attribute called ResponseType which you can use to decorate on an action to describe the actual response type for a given action..

Related

Why Swagger is not picking up the summary of an ApplicationService method in ABP Framework?

I have the following application service method.
public class MyAppService : AsyncCrudAppService<Entity, Dto, Guid, GetAllRequest, CreateRequest, UpdateRequest, GetRequest, DeleteRequest>, IMyAppService
{
/// <summary>
/// Return cities associated with zip code
/// </summary>
/// <param name="zipCode">Zip code to search. If null all cities are returned.</param>
/// <returns>Cities associated with zip code.</returns>
/// <exception cref="EntityNotFoundException">If zip code is provided but no associated city is found</exception>
/// <response code="404">If no city with zip code found</response>
[ProducesResponseType(StatusCodes.Status200OK)]
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task<GetCitiesByZipCodeResponse> GetCitiesByZipCode(int? zipCode = null)
{
...
}
}
Even though I have a summary describing what the endpoint does, it is not displayed in swagger. What is the right way to add rich information to Swagger about app service methods?
It did pick up the effect of ProducesResponseType(StatusCodes.Status404NotFound) and showing 404 as possible response though.
Swagger for GetCitiesByZipCode
AppServices are automatically converted to Controllers. But your custom Swagger attributes are stripped off. If you have a such requirement, then create a new MyContoller and call your AppService methods inside the Controller. And disable remote service function for your Appservice with the following attribute
[RemoteService(IsEnabled = false)]
https://docs.abp.io/en/abp/latest/API/Auto-API-Controllers#remoteservice-attribute

How to get JSON formatting when adding Swashbuckle remarks?

I have been following this tutorial on Swashbuckle but when I add remarks they appear as regular text not the JSON shown in the remarks section. Is it possible to get JSON formatting?
/// <remarks>
/// Sample request:
///
/// POST /Todo
/// {
/// "id": 1,
/// "name": "Item1",
/// "isComplete": true
/// }
///
/// </remarks>
Make sure Sample Request is not indented!

Swashbuckle.AspNetCore required query string parameter

I have an ASP.NET Core v2.1 project with Swashbuckle.AspNetCore package.
My code is:
/// <summary>
/// Set new android token for the current driver
/// </summary>
/// <remarks>
/// Sample request:
///
/// PUT /SetToken?token=new_token
///
/// </remarks>
/// <param name="token">can't be null or empty</param>
/// <returns></returns>
/// <response code="204">If executed successfully</response>
/// <response code="400">if token is null or empty</response>
/// <response code="404">if user is not a driver; if driver is not found (removed etc); if user does not have a profile</response>
[ProducesResponseType(204)]
[ProducesResponseType(400)]
[ProducesResponseType(404)]
[HttpPut]
[Route("SetToken")]
[UserIsNotDriverException]
[NullReferenceException]
[DriverWithoutProfileException]
public async Task<IActionResult> SetToken([FromQuery]string token)
{
I want to mark query parameter as required. How can I do it? Pay attention, I pass parameter in query string, not inside body etc
You can add the BindRequired attribute to your parameter.
public async Task<IActionResult> SetToken([FromQuery, BindRequired]string token)
You can do it like this.
public async Task<IActionResult> SetToken([FromQuery, SwaggerParameter("Token Description", Required = True)]string token)
Using this library Swashbuckle.AspNetCore.Annotations will help.

WCF Data Service - Restrict visibility and logging queries

I have two questions related to WCF Data Service:
is there a way to restrict the entities visible to a user according to her privileges ? For instance user in role super-user should be able to query the full 'Contact' entity but user with less privileges would only be able to see specific properties of the 'Contact' entity.
whenever a user runs a query on the service, I would like this to be logged in a database for audit purpose. Is this possible ?
1) There is the concept of interceptors: http://msdn.microsoft.com/en-us/library/dd744842.aspx
But I think they won't satisfy you in your case:
With change interceptors you can handle requests which try to change a specific entity. This could help you to avoid users without certain privileges to add/change/delete contact entities. With QueryInterceptors you can handle GET-Requests. But they don't allow you to restrict certain properties of your contact entity.
You are not the first with such requirements -> WCF Dataservice - modify object before returning results?
Maybe you could use a combination of a (custom) ServiceOperation and a View to handle this.
2) Yes, you can do this for instance by handling the ProcessingRequest-Event:
public class YourService : DataService<Entities>
{
/// <summary>
/// The logger.
/// </summary>
private readonly LogWriter logger;
/// <summary>
/// Initializes a new instance of the <see cref="YourService"/> class.
/// </summary>
public YourService()
{
this.logger = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
this.ProcessingPipeline.ProcessingRequest += this.ProcessingPipelineProcessingRequest;
}
/// <summary>
/// OnProcessingRequest
/// </summary>
/// <param name="sender">source</param>
/// <param name="e">event args</param>
public void ProcessingPipelineProcessingRequest(object sender, DataServiceProcessingPipelineEventArgs e)
{
this.logger.Write(new LogEntry { Message = "SOP ProcessingPipelineProcessingRequest: Unauthorized Access", Severity = TraceEventType.Warning })
}
}
You can find all those ProcessingPipeline-Events here: http://msdn.microsoft.com/en-us/library/system.data.services.dataserviceprocessingpipeline(v=vs.103).aspx

NServiceBus, NHibernate and Multitenancy

We're using NServiceBus to perform document processing for a number of tenants.
Each tenant has their own database and we're using NHibernate for data access. In the web application we're using our IoC tool (StructureMap) to handle session management. Essentially we maintain a session factory for each tenant. We're able to identify the tenant from HttpContext.
When we kick off document processing using NServiceBus we have access to the tenant identifier. We need this tenant id to be available throughout the processing of the document (we have 2 sagas and fire off a number of events).
We would need to create a NHibernate SessionFactory for each tenant so would need some way of obtaining the tenant id when we configure StructureMap.
I've seen a few posts suggesting to use a message header to store the tenant identifier but am unsure how to:
Set a message header when we first submit a document (sending a SubmitDocumentCommand)
Reference the header when we configure StructureMap
Access the header within our sagas/handlers
Ensure the header flows from one message to the next. When we send a SubmitDocumentCommand it is handled by the DocumentSubmissionSaga. If the submission succeeds we will send off a DocumentSubmittedEvent. We'd want to make sure the tenant id is available at all points in the process.
I believe with this information I can successfully implement multitenancy with NHibernate but anything more specific to this scenario would be appreciated.
You can flow the header using a message mutator that registers itself: Here is a quick example from my own code. And you can always use Bus.CurrentMessageContext.Headers to set/get to the header anywhere...
Hope this helps :)
/// <summary>
/// Mutator to set the channel header
/// </summary>
public class FlowChannelMutator : IMutateOutgoingTransportMessages, INeedInitialization
{
/// <summary>
/// The bus is needed to get access to the current message context
/// </summary>
public IBus Bus { get; set; }
/// <summary>
/// Keeps track of the channel
/// </summary>
/// <param name="messages"></param>
/// <param name="transportMessage"></param>
public void MutateOutgoing(object[] messages, TransportMessage transportMessage)
{
if (Bus.CurrentMessageContext != null &&
Bus.CurrentMessageContext.Headers.ContainsKey("x-messagehandler-channel"))
{
if (!transportMessage.Headers.ContainsKey("x-messagehandler-channel"))
{
transportMessage.Headers["x-messagehandler-channel"] =
Bus.CurrentMessageContext.Headers["x-messagehandler-channel"];
}
}
}
/// <summary>
/// Initializes
/// </summary>
public void Init()
{
Configure.Instance.Configurer.ConfigureComponent<FlowChannelMutator>(DependencyLifecycle.InstancePerCall);
}
}