Swagger UI Response Example Asp.Net Core Web Api - c#

I'm using Swagger.AspNetCore to document my api. So far i was happy to use xml comments to generate response model examples until i reach the point when i've got to document embeded object. So i have simple model:
public class SummaryResult
{
/// <summary>Total Cost.</summary>
/// <value>Total Cost.</value>
/// <example>6433.2</example>
public double TotalCost { get; set; }
/// <summary>Owner.</summary>
public Owner Owner { get; set; }
}
public class Owner
{
/// <summary>Owner Name.</summary>
/// <value>Owner Name.</value>
/// <example>Michael</example>
public string Name { get; set; }
}
And Swagger UI document it only for TotalCost, Owner property just skipped whatever i do. Does anyone have a clue why this can happen? And how to fix it.
I know how to deal with List - just put on top xml comment like <list></list> but it's not my case.
Thank you

I just tested this and it shows fine on my end:
http://swagger-net-test.azurewebsites.net/swagger/ui/index#/ActionFilter/ActionFilter_Get
Here is how that looks like on the model tab:
As you can see in the image it does show the summary and the example value.
Here is the code:
https://github.com/heldersepu/Swagger-Net-Test/blob/master/Swagger_Test/Controllers/ActionFilterController.cs#L29
Educated guess there could be something else removing those elements.

Related

What is an appropriate MVC-based OOP design for my case?

Suppose the following baseline design: I have a class CarElement which holds properties and methods related to both visual representation and data model/logic representation of a car:
class carElement
{
// UI related properties and methods:
public Size DrawSize { get; set; }
public Point Location { get; set; }
public void Draw()
{
// do something...
}
// data model / logic related properties and methods:
public double weight { get; set; }
public string manufacturer { get; set; }
public double CalculatePrice()
{
// do something...
return 0;
}
}
The usage of this class is as follows: Multiple instances of carElement are drawn to some canvas. Clicking each drawn car shows the properties of that car in a property grid by using propertygrid.SelectedObject = InstanceOfcarElement.
In my opinion, this design is flawed because data model and visual representation are not separated in the class design. I would like to improve the design towards MVC and I am seeking advice on good design decisions.
My current take on this would be to separate above class carElement into something like the following two classes.
class carUIElement // organizes visual representation of a car
{
public Size DrawSize { get; set; }
public Point Location { get; set; }
private carDataElement linkedCarDataElement;
public void Draw()
{
// do something...
}
}
class carDataElement // organizes data model organization of a car
{
public double weight { get; set; }
public string manufacturer { get; set; }
private carUIElement linkedCarUIElement;
public double CalculatePrice()
{
// do something...
return 0;
}
}
With that approach, the following are unclear to me:
carUIElement should know the carDataElement it is linked to, and vice versa. Are there better design approaches to this than the simple linking in above Code?
How would I best show both the UI and data model properties on the property Grid, when the drawn UIElement is clicked?
Is the overall approach viable? What about the above open points? I am missing the experience to judge that, so I would be grateful for your comments. Thank you.
Well while we should always be careful not to over intellectualize stuff, after all we as programmers are more masons than artist and even if Notre Dame church is just a construction and not art, no always will be required exorbitant decoration and acoustic chambers, suppose the next version will be as grand as the previous :)
What do i mean? I propose pragmatism with MVC, so if and if in early infancy of the program, it can have the ui model, also sometimes called the data transfer object, be identical to the logical model, that is not in itself an anti-pattern imo.
Obviously once bulding ui, we begin to have released instances with presumed constructs and when it starts to limit development of the product, how it is presented, typically when you need more info than is relevant to ui, stored on the entity, then you can lock the interface by inventing the DTO model objects and party on with the initial model.
So I get where you're going with what's behind why you might want to separate it.
Then again often we have web frontends, especially with mvc and then mostly it will be no longer a databound view, but a MVVM thingy like like Angular, React, Vue or even Blazor if for some reason you might want that, or the tradition Razor pages, really? in new development??
I try not to put anything in the DTO classes that would be lost if only the serialized JSON version is available to your view engine. So that when modernization happens, your controller/ api doesn't have to principally change.
So seperate classes for seperate concerns an no logic in data access or transfer classes, my suggestion would be something along the lines below, but to end up with your questions:
a) Linking with a navigation property in your data model makes sense if you use it to load for instance using entity framework, it is required.
In Your UI type the frequency is key, typically we like to push all data into the points so that they need nothing else to perform, but this makes sense if the class is being serialized and deserialized and you use a tool like AutoMapper to move to and from, if You're in a windows client like WPF hey your model is already on the client and already loaded up for MVVM, you're in such a much better place that you may not honestly care for front-end types, until they need to vary.
b) the question is do you always want to show both or can you hide the cardata element until they ask for it, that would dictate the choice to either let a DTO include the data from the relation or just the foreign key and have an extra lookup method available imo.
So suggestion brief:
/// <summary>
/// Drawing is a separate concern of the application
/// </summary>
class DrawManager
{
public void DrawCar(CarBase car) { }
}
/// <summary>
/// So is calculating prices
/// </summary>
class PriceManager
{
decimal CalculateCarPrice(CarBase car) { throw new NotImplementedException(); }
}
/// <summary>
/// The 2 classes share properties, invent a base class to abide by the DRY principle
/// </summary>
class CarBase
{
public Size DrawSize { get; set; }
public Point Location { get; set; }
}
/// <summary>
/// Now they are identical
/// </summary>
class carElement : CarBase
{
carDataElement CarData { get; set; }
}
/// <summary>
/// Now they are identical
/// </summary>
class carUIElement : CarBase
{
carDataElement linkedCarDataElement;
}
/// <summary>
/// The data about a car, in RDBMS typically normalized into a seperate entity like you have,
/// does UI really need any of them? Is it always needed when other members are accessed?
/// </summary>
/// <remarks>
/// we could choose to have the data model have a navigation property and then let the ui member not have it and give it a method to ackquire it,
/// but then that shouldn't get done to early and well if it always needs it, it is not yet a seperate datatype justification for the ui aspect
/// </remarks>
class carDataElement
{
public double weight { get; set; }
public string manufacturer { get; set; }
}

Update asp.net gridview element from json specification

I have a simple aspx page "Default" with a code behind. The code behind has a set of simple methods.
What I'm looking to do is to create a method OnGridViewChange() - see the mockup below - which is called whenever the user changes a row in the gridview. The row updates a local list of Rows and then converts to object to a json string which is showed to the user.
Essentially what I'm building is a glorified json viewer in asp.net web forms which takes a json string, displays it as a table and then updates the json and table on user changes.
I think I have most of the major methods outlined below, but what I need help with is the OnUpdate method,
public partial class _Default : Page
{
public class FoobarRow
{
public string Name { get; set; }
public int NumberOfHats { get; set; }
}
public List<FoobarRow> FoobarRows { get; set; }= new List<FoobarRow>();
/// <summary>
/// Vera important json formatted string. Gets updated when gridview changes
/// </summary>
public string Json { get; set; }
/// <summary>
/// Updates gridview on the page from the json entered by the user on a previous page
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
protected void Page_Load(object sender, EventArgs e)
{
FoobarRows = JsonConvert.DeserializeObject<List<FoobarRow>>(GetJsonFromUserWhenPageLoads());
UpdateGridviewFromList();
}
/// <summary>
/// Actually updates the gridview from the list of FoobarRows
/// </summary>
private void UpdateGridviewFromList()
{
ApplicationGridView.DataSource = FoobarRows;
ApplicationGridView.DataBind();
}
/// <summary>
/// Is called whenever user edits any row in the gridview and saves the changes. Updates the json and the local list of rows
/// </summary>
/// <param name="rows"></param>
public void OnGridViewChange(List<FoobarRow> rows)
{
FoobarRows = rows;
DisplayCurrentJsonOnPageForUser(JsonConvert.SerializeObject(rows));
UpdateGridviewFromList();
}
public string GetJsonFromUserWhenPageLoads()
{
//Finish later
return "some json the user will have entered on a previous page and will be loaded into a label or something of the like";
}
public void DisplayCurrentJsonOnPageForUser(string json)
{
//Finish later
}
}
Having looked around, I found this documentation from Microsoft https://msdn.microsoft.com/en-us/library/ms972948.aspx?f=255&MSPPError=-2147217396 about the aspx gridview but it seems needlessly complicated for my usecase.
Does anyone know of any datagrid plugin for webforms or other asp.net element that would allow me to tie changes to a simple event such as OnGridViewChange(). I'm new to web forms and the above mentioned article from Microsoft is the best I've managed to find but I feel like there must be a better way!
Apparently this can be achieved by using this event model found here.
https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.rowupdating%28v=vs.110%29.aspx?f=255&MSPPError=-2147217396

How to Deserialize json that has properties containing different objects?

I'm currently working on a .NET client for the Zoho Books API in order to integrate some data within my organization. I have been struggling with deserializing the json returned by the API. The problem has been because of inheritance and varying property names. I think I'm looking at creating a custom converter in order to avoid creating response types for every model for the sake of a few varying fields.
I was able to create a custom converter that works for parent responses which look like this:
{
"code" : 0,
"message" : "success",
"invoice" : { // This field varies by model
"invoice_id" : "..."
}
}
I have created a gist for this custom converter.
One of the issues with the custom converter is that when I pass the generic return type down from the web client, I need it in either in the base response format or the paginated response format, and generics are failing me here. My converter doesn't work for paginated responses.
I defined my base type of ZohoBooks Response as so:
namespace ZohoBooks4Net.Responses
{
public class ZohoBooksResponse<T> : IZohoBooksResponse<T>
{
/// <summary>
/// Zoho Books error code. This will be zero for a success response and non-zero in case of an error.
/// </summary>
[JsonProperty("code")]
public int Code { get; set; }
/// <summary>
/// Message for the invoked API.
/// </summary>
[JsonProperty("message")]
public string Message { get; set; }
/// <summary>
/// Comprises the invoked API’s Data.
/// </summary>
public T Resource { get; set; }
}
}
Resource is what I'm calling the third field in the response.
However, when the response returns as paginated, it adds another field.
{
"code": 0,
"message": "success",
"contacts": [
{ "..." }
],
"page_context": {
"page": 1,
"per_page": 200,
"has_more_page": false,
"applied_filter": "Status.All",
"sort_column": "contact_name",
"sort_order": "D"
}
}
So I created this object that describes it:
namespace ZohoBooks4Net.Responses.PaginatedResponses
{
public class PaginatedResponse<T> : ZohoBooksResponse<T>, IPaginatedResponse<T>
{
[JsonProperty("page_context")]
public PageContext Context { get; set; }
}
public class PageContext
{
[JsonProperty("page")]
public int Page { get; set; }
[JsonProperty("per_page")]
public int PerPage { get; set; }
[JsonProperty("has_more_page")]
public bool HasMorePage { get; set; }
}
}
If anyone has any solutions I would really appreciate it.
Books already hosted .Net library in github. In Subscription java client, page context and resources handled separately.
Have you tried using the json2csharp web application tool? It will create the classes needed from your JSON response and a root object which can be used with the Newtonsoft JsonCovnert's DeserializeObject method.
Taking a referenced post from a commenter, I implemented the ReadJson method created by poster of the article. This solved my issue. Here's a link to DynamicPropertyNameConverter on Github Gist.

Implementing a feature to track if the user is repeating a search

I have a view model that represents all the fields available for searching. I'd like to add some logic that would be able to identify if the search values are all the same and determine whether to hit the DB again for their query.
I think I would have to do something like..
after user submits form save form values to some
temporary field.
upon second submission compare temp value to form values collection.
if values are equal set property in view
model IsSameSearch = true
I'd like to use the Post Redirect Get Pattern too. So that My search View doesn't do anything except post the form values to another action that processes and filters the data, which is then "Getted" using Ajax.
The SearchViewModel contains many many search parameters. Here is an abbreviated version.
public bool UseAdvancedSearch { get; set; }
public bool isSameSearch { get; set; }
/// <summary>
/// Gets or sets the page.
/// </summary>
[HiddenInput]
[ScaffoldColumn(false)]
public int Page { get; set; }
[HiddenInput]
[ScaffoldColumn(false)]
public string SortOption { get; set; }
/// <summary>
/// Gets or sets the address keywords.
/// </summary>
[Display(Name="Address")]
public string AddressKeywords { get; set; }
/// <summary>
/// Gets or sets the census.
/// </summary>
public string Census { get; set; }
/// <summary>
/// Gets or sets the lot block sub.
/// </summary>
public string LotBlockSub { get; set; }
/// <summary>
/// Gets or sets the owner keywords.
/// </summary>
[Display(Name="Owner")]
public string OwnerKeywords { get; set; }
/// <summary>
/// Gets or sets the section township range.
/// </summary>
public string SectionTownshipRange { get; set; }
/// <summary>
/// Gets or sets the strap.
/// </summary>
///
[Display(Name="Account Number/Parcel ID")]
public string Strap { get; set; }
/// <summary>
/// Gets or sets the subdivision.
/// </summary>
public string Subdivision { get; set; }
/// <summary>
/// Gets or sets the use code.
/// </summary>
[Display(Name = "Use Code")]
public string UseCode { get; set; }
/// <summary>
/// Gets or sets the zip code.
/// </summary>
[Display(Name="Zip Code")]
public string ZipCode { get; set; }
If you are getting data from Entity Framework you could cache the data at EF level. Look at the package entity framework extended https://github.com/loresoft/EntityFramework.Extended. It is as simple as adding method .FromCache () to the query you use to retrieve and filter the data and it will cache the query result. Make sure you load all the data required using includes etc.
You wouldn't have to worry about same search in model as the caching provider would look at filter settings and determine that it was different. Alternatively cache the data before filtering and then filter the cached results. This is more appropriate if you have lots of filter parameters with significant variance as you will only have to cache 1 large result rather than thousands of smaller results.
You can get more advanced and specify cache period e.g. Cache for 10 minutes
What you are describing is called caching.
One way to accomplish that in your scenario would be to implement GetHashCode() in a way that it would take into account all your fields/properties to compute a unique value. That way you can use your Hash as the key entry in your cache, and store the results with that key.
For that actual caching you could just use the MemoryCache class provided by the .Net Framework if you are not deploying to a web farm.
Also, if you are familiar with IoC and DI (such as using Unity), things like this can be implemented as an Interceptor, and only requiring you to add an attribute to the method you'd like to cache. That way you implement caching only once as a cross-cutting concern and not fill up your application code with things like this.

C# save/retrieve an array of structures from settings file

I have a simple question (I think) that I'm not making much progress finding an answer to with Google. I have a structure as follows:
/// <summary>
/// A class to represent the sync settings for a single camera.
/// </summary>
public class CameraSyncSettings
{
public string ID { get; set; }
public string SyncPath { get; set; }
public bool OverwriteExisting { get; set; }
};
And then an array of these in the program, one for each camera:
List<CameraSyncSettings> MyCameraSettings = new List<CameraSyncSettings>();
Now, what I want to do is have a property in my settings such that I can read/write this array into it to persist the information between sessions.
How can I do this and what is the best/most efficient way?
You can achieve it by using Properties.Settings of type ListDictionary
Example:
Properties.Settings.Default.Example.Add("Setting1", new CameraSyncSettings());
Properties.Settings.Default.Example.Add("Setting2", new CameraSyncSettings());
Properties.Settings.Default.Example.Add("Setting3", new CameraSyncSettings());
Properties.Settings.Default.Save();
see link for more information : http://msdn.microsoft.com/en-us/library/aa730869(v=vs.80).aspx
NB: You can set the Scope of Properties.Settings.Default.Example to Application or User
As we've cleared in the comments you want to use app.config: this project should pretty much cover all your needs.

Categories

Resources