How to display body as html forms using Swagger in ASP.NET Core
In Swagger is it possible to have the body represented as HTML forms as opposed to a JSON string? and how would one achieve this?
In django for example I can input the JSON via html forms (Yes this is a simple example, but more complex objects can be a little annoying to write JSON, especially where the field is a foreign key and you can't remember the entries in that table).
In Swagger my UI looks like, ideally Id would also not be a required input as it is auto-generated.
From the request body drop down box I only have these choices.
Any help much appreciated.
1 answer
-
answered 2021-01-18 00:24
Soggy
As Andy correctly noted in the comments the answer is to add the [FromForm] annotation to the argument in the endpoint function
See also questions close to this topic
-
getting prob on reading nested class c#
Hi really need assistance here,
I have 2 classes which i use to read from json i need to save into 2 tables (root and participants) in 1 submission. i will have only 1 root with 1 or many participants. i have no prob saving the root but i have prob reading if i am sending both (root with participants}
[ { "NoIC": "122233243", "Nama": "TEST NAME", ... "Participant": [ { "Nama" : "Participant 1", "Bil" : "1", ... }, { "Nama" : "Participant 2", "Bil" : "1", .... } ] } ] public class Participant { public string ref_no { get; set; } public string Nama { get; set; } public string Bil { get; set; } public string Price { get; set; } public string RequestedPlace { get; set; } public string RequestedExe { get; set; } public string RequestedDate { get; set; } public string Type { get; set; } } public class Root { public string NoIC { get; set; } public string Nama { get; set; } public string HPNo { get; set; } public string Email { get; set; } public string Type { get; set; } public string RegisterBy { get; set; } public List<Participant> Participant { get; set; } } public string RegisterApplication([FromBody] Root register, Participant participants) { try { using (MySqlConnection sql = new MySqlConnection(_connectionString)) { using (MySqlCommand cmd = new MySqlCommand("GetInsertApplication", sql)) { sql.Open(); cmd.CommandType = System.Data.CommandType.StoredProcedure; // cmd.Parameters.AddWithValue("@refNo", register.RefNo); cmd.Parameters.AddWithValue("@NoIC", register.NoIC); cmd.Parameters.AddWithValue("@Nama", register.Nama.ToUpper()); cmd.Parameters.AddWithValue("@NoFonHp", register.HPNo); cmd.Parameters.AddWithValue("@Email", register.Email); cmd.Parameters.AddWithValue("@refType", register.Type); cmd.Parameters.AddWithValue("@RegisterBy", register.RegisterBy); ...... ref_no = refnoParameter.Value.ToString(); //will pass this refno to child/participant
my prob is here. i need to read the child (1 Root can have more than 1 participant)
List<Participant> participants = new List<Participant>(); using (MySqlCommand cmd2 = new MySqlCommand("GetInsertParticipant", sql)) { cmd2.Parameters.AddWithValue("@ref_no", ref_no); cmd2.Parameters.AddWithValue("@Nama", participant.Nama.ToUpper()); cmd2.Parameters.AddWithValue("@Bil", participant.Bil); cmd2.Parameters.AddWithValue("@Price", participant.Price); cmd2.Parameters.AddWithValue("@RequestedPlace", participant.RequestedPlace); cmd2.Parameters.AddWithValue("@RequestedExe", participant.RequestedExe); cmd2.Parameters.AddWithValue("@RequestedDate", participant.RequestedDate); cmd2.Parameters.AddWithValue("@Type", participant.Type); cmd2.Connection.Open(); cmd2.CommandType = CommandType.Text; cmd2.ExecuteNonQuery();
}}}}}
anybody please, i stuck here for few days and i really need your help/opinion. thaks in advanced
-
How do I insert input from form to database?
My model looks like this:
public class Customer { public int CustomerId { get; set; } [Required(ErrorMessage = "Please enter a valid first name")] public string FirstName { get; set; } [Required(ErrorMessage = "Please enter a valid last name")] public string LastName { get; set; } [Required(ErrorMessage = "Please enter a valid address")] public string Address { get; set; } public string Email { get; set; } [Required(ErrorMessage = "Please enter a valid city")] public string City { get; set; } public string Phone { get; set; } [Range(1, 5, ErrorMessage = "Please enter a valid country")] public int CountryId { get; set; } public Country Country { get; set; } [Required(ErrorMessage = "Please enter a valid state")] public string State { get; set; } [Required(ErrorMessage = "Please enter a valid postal code")] public string PostalCode { get; set; } public string fullname => FirstName + LastName; }
My controller looks like this:
public class CustomerController : Controller { private CustomerContext context { get; set; } public CustomerController(CustomerContext ctx) { context = ctx; } public IActionResult List() { var customers = context.Customers.ToList(); return View(customers); } [HttpGet] public IActionResult Add() { ViewBag.Action = "Add"; ViewBag.Countries = context.Countries.OrderBy(c => c.Name).ToList(); return View("Edit", new Customer()); } [HttpGet] public IActionResult Edit(int id) { ViewBag.Action = "Edit"; ViewBag.Countries = context.Countries.OrderBy(c => c.Name).ToList(); var customer = context.Customers .Include(c => c.Country) .FirstOrDefault(c => c.CustomerId == id); return View(customer); } [HttpPost] public IActionResult Edit(Customer customer) { string action = (customer.CustomerId == 0) ? "Add" : "Edit"; if (ModelState.IsValid) { if (action == "Add") { context.Customers.Add(customer); } else { context.Customers.Update(customer); } context.SaveChanges(); return RedirectToAction("List", "Customer"); } else { ViewBag.Action = action; ViewBag.Countries = context.Countries.OrderBy(c => c.Name).ToList(); return View(customer); } }
I also have a DbContext file with data i created to test other things:
public class CustomerContext : DbContext { public CustomerContext(DbContextOptions<CustomerContext> options) :base(options) { } public DbSet<Customer> Customers { get; set; } public DbSet<Country> Countries { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Country>().HasData( new Country { CountryId = 1, Name = "Canada"}, new Country { CountryId = 2, Name = "United States"}, new Country { CountryId = 3, Name = "United Kingdom" }, new Country { CountryId = 4, Name = "Mexico" }, new Country { CountryId = 5, Name = "Russia" } ); modelBuilder.Entity<Customer>().HasData( new Customer { CustomerId = 1, FirstName = "Bruce", LastName = "Wayne", Phone = "416-123-4567", Email = "bruce.wayne@gmail.com", CountryId = 1, Address = "123 sesame street", City = "Toronto", PostalCode = "L812A", State = "Ontario" } ); }
I already did the add-migration and updated my database via the package manager console. I created a form in the view that looks like this:
Cancel<form method="post" asp-action="Add"> <div asp-validation-summary="All"> <div> <label asp-for="FirstName">First Name</label> <input type="text" name="FirstName" asp-for="FirstName" /> </div> <div> <label asp-for="LastName">Last Name</label> <input type="text" name="LastName" asp-for="LastName" /> </div> <div> <label asp-for="Address">Address</label> <input type="text" name="Address" asp-for="Address" /> </div> <div> <label asp-for="City">City</label> <input type="text" name="City" asp-for="City" /> </div> <div> <label asp-for="State">State</label> <input type="text" name="State" asp-for="State" /> </div> <div> <label asp-for="PostalCode">Postal Code</label> <input type="text" name="Postal Code" asp-for="PostalCode" /> </div> <div> <label asp-for="CountryId">Country</label> <select name="Country" asp-for="CountryId"> @foreach (Country country in ViewBag.Countries) { <option value="@country.CountryId">@country.Name</option> } </select> </div> <div> <label asp-for="Email">Email</label> <input type="text" name="Email" asp-for="Email" /> </div> <div> <label asp-for="Phone">Phone</label> <input type="text" name="Phone" asp-for="Phone" /> </div> <input type="hidden" asp-for="CustomerId" /> </div> <button type="submit" value="Save" asp-controller="Customer" asp-action="List">Save</button>
I've tried looking up multiple different solutions to solve my issue but I cant seem to figure out how to solve it. If someone could help me that would be much appreciated. thanks in advance.
-
Submit button doenst work with script asp.net mvc5
I have a maybe simple problem but I don`t have that much experience with scripts:
I have this Skript in my _Layout.cshtml:
<script> $('button').click(function () { $(this).prop('disabled', true); }); </script>
and one of my views:
@using (Html.BeginForm("Create", "Home", FormMethod.Post, null)) { @Html.AntiForgeryToken() <div class="mt-5 d-flex flex-row"> <textarea class="form-control" name="TextArea"></textarea> <button class="btn btn-secondary btn-block mt-2 post-btn" type="submit" id="PostButton">Post</button> </div> }
This form works great without the script, but for any reason with the script it doesn`t work.
I placed the script in the _layout.cshtml because I want to have it for all buttons in my asp.net page.
After click on the button the button is disabled - as I wish - but the action result "Create" in the HomeController will not called.
I think I need to extend the script but can someone help me how to do it?
Thanks all
-
Authenticate users on AWS Cognito with OpenId Connect (OKTA) for .Net Core 3.x
I have a .net core 3.x web API that authenticates users on aws cognito in the cognito userpool. AWSSDK provides good support for that.
I have to extend my application support to include okta (openId Connect) users via cognito. I have already synced up the users and I can authenticate them successfully using the default UI provided by cognito.
I am not able to find any examples/documentation on how I can authenticate these users on OKTA (openId-connect) via an API call from my application. I am using postman to call my API authenticate endpoints.
Is there any way I can make a postman call to the cognito/openId connect (send user creds in the body/request) and authenticate the user to get the jwt token back in response in?
Most examples I found are old .net core 2.0 and earlier and they use mvc and razor page.
Thank you RDG
-
ASP.Net 5 Web API: Use own Login / Token system?
Is it really a bad idea to create a own Login system with tokens? I know there are built in identity services in .NET and for a token based authentification nearly everyone says "Jwt"... But I prefer to do as much as possible by my own, so I understand what (my) code is doing and can easily customize things.
This is my general idea for a login system with blazor (.net hosted), other login systems like google & co are NOT planned:
- Public API endpoint "API/Login" with params "username" and "password"
- The client (Blazor App for example) sends user and hashed password and encrypts both (so sniffers can't read anything, SSL will be on top ofc)
- The server decrypts this information by a shared key
- The server checks the database for the user and password-hash combination
- If user/password was correct (found), a generated API Key / Token will be generated (for an easy example, a new Guid, but not the UserId)
- The client saves this API Key / Token (localstorage for example)
- The client sends the API Key / Token on every web API request via the headers
The simplyfied code could be (NOT tested, just pseudo):
API-Controller:
[HttpPost] [Route("API/Login")] public string Login(string username, string passwordHash) { if (!string.IsNullOrEmpty(username) && !string.IsNullOrEmpty(passwordHash)) { var user = context.Users.Where(u => u.Username = username && u.PasswordHash = passwordHash && u.TokenExpires > DateTime.Now).FirstOrDefault(); if (user != null) { string exampleToken = Guid.NewGuid().ToString(); user.Token = exampleToken; context.Users.Update(user); context.SaveChanges(); return exampleToken; } } return null; } [HttpGet] [Route("API/WeatherForecast")] public IEnumerable<WeatherForecast> Get() { var customToken = Request.Headers["CustomToken"].FirstOrDefault(); if (customToken != null && context.Users.Where(u => u.Token == customToken)) { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }) .ToArray(); } return null; }
API-Call:
protected override async Task OnInitializedAsync() { Http.DefaultRequestHeaders.Add("CustomToken", "000b5244-9477-4119-8456-8451b197d61f"); forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("WeatherForecast"); }
What I DONT like with the default security approaches:
- For me hard to understand, just too much code / services / options (it's more a "blackbox" for me) for a "simple" login
- Hard to customize without changing all the services
- Hackers will try to check security issues for the most common security setups (they don't know much about my security system, if I use a custom one)
Maybe I did miss something... What are the big cons for a custom security system?
-
how to show country-wise search results from single db in dotnet application
i am developing a web app for used goods buy and sale and the site will be launched in few countries. But i am stuck on how to architect the db for displaying the search results countrywise from the same website and same SQL db when people search a product. Thanks a lot for your help.
-
Apply claims-based authorization policy to Swagger UI in .Net Core 3.1
I've made an API using ASP.Net Core 3.1 and I've added Swagger UI at the root of the site using Swashbuckle. Maybe this is a trivial question, but I'd like the Swagger UI to be accessible only to authorized users (i.e. not publicly available). I've read a lot of posts about how Swagger handles the API authorization scheme, but none about the Swagger UI itself. In particular I need to restrict the access to the static files it creates through some
[Authorize(Policy="MyCustomPolicy")]
attribute or equivalent, so only users with a specific claim in their identity can access the UI. This condition is required only on the Swagger UI, because the API itself already has access control through Bearer authentication and that works just fine.How is this claims requirement added to Swagger UI?
This is how I add the Swagger service:
// Register the Swagger Generator service. This service is responsible for genrating Swagger Documents. // Note: Add this service at the end after AddMvc() or AddMvcCore(). services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = "MySystem API", Version = "v1", Description = "API for MySystem.", Contact = new OpenApiContact { Name = "MyCompany S.A.", Email = string.Empty, Url = new System.Uri("https://contoso.com/"), }, }); var filePath = System.IO.Path.Combine(System.AppContext.BaseDirectory, "MySystem.Web.xml"); c.IncludeXmlComments(filePath); c.CustomSchemaIds(x => x.GetCustomAttributes(false).OfType<DisplayNameAttribute>().FirstOrDefault()?.DisplayName ?? x.Name); });
This is how I add Swagger to my builder:
// Enable middleware to serve generated Swagger as a JSON endpoint. app.UseSwagger(); // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.), // specifying the Swagger JSON endpoint. app.UseSwaggerUI(c => { c.SwaggerEndpoint("/swagger/v1/swagger.json", "MySystem API v1"); // To serve SwaggerUI at application's root page, set the RoutePrefix property to an empty string. c.RoutePrefix = string.Empty; });
Thanks in advance.
-
Using OpenAPI 3 with Node.JS
I would like to integrate OpenAPI 3 into my node.js project and take advantage of the Swagger tools that are available.
I noticed that the swagger npm module hasn't been updated in five years. There are other questions, such as this one (How to use OpenAPI 3.0 in Node.js?) which have basically gone unanswered.
A superficial web search yields me no results.
Does anyone have some ideas/suggestions on how to implement the OpenAPI 3.* standard into swagger apps in node? Even if you've found a tutorial or some description on how to do this manually, I would be most grateful for some direction and advice.
I tried just simply putting the OpenAPI 3 standard in the editor (
swagger project edit
) as you would the online editor, and it goes crazy with errors. I tried manually updating the swagger.yaml document, which also just leads to the node application crashing.The updates from the new standard (3.* vs 2) are so much easier to read, implement and reuse, which is why I'm asking about this. Again, any direction or help would be greatly appreciated.
-
Is it possible to combined a defined schema in an array property with additional properties?
I have my model schemas defined and I want to reference one of them in an array property, with additional attributes. If I didn't have the additional properties I could of course do this:
* @OA\Response( * response=200, * description="", * @OA\JsonContent( * @OA\Property(property="data", type="object", allOf={ * @OA\Schema(ref="#/components/schemas/Site"), * @OA\Schema( * @OA\Property(property="groups", type="array", @OA\Items(ref="#/components/schemas/Group") * ) * }) * ) * ),
But what I want to do is something like this:
* @OA\Response( * response=200, * description="", * @OA\JsonContent( * @OA\Property(property="data", type="object", allOf={ * @OA\Schema(ref="#/components/schemas/Site"), * @OA\Schema( * @OA\Property(property="groups", type="array", @OA\Items( * @OA\Schema(ref="#/components/schemas/Group"), * @OA\Property(property="additional_property", type="string") * ) * ) * }) * ) * ),
Is this possible?
-
What's the JSON schema for default Spring error responses?
I'm generating an OpenAPI definition using the springdoc library and I would like to describe the response types of default exceptions that are thrown deep in some service.
In particular there is a standard error response returned when
ResponseStatusException
exceptions are thrown and they produce this JSON:{ "timestamp": "2021-02-23T17:56:20.523+00:00", "status": 400, "error": "Bad Request", "message": "The user provides contradictory organization information", "path": "/api/vehicles" }
I haven't found a single class that implements these fields and suspect that these fields are simply added one by one to the response.
An even more complex error response are validation responses. I didn't find a class describing these errors either:
{ "timestamp": "2021-02-23T17:58:09.662+00:00", "status": 400, "error": "Bad Request", "message": "Validation failed for object='addVehicleDto'. Error count: 1", "errors": [ { "codes": [ "Pattern.addVehicleDto.licensePlate", "Pattern.licensePlate", "Pattern.java.lang.String", "Pattern" ], "arguments": [ { "codes": [ "addVehicleDto.licensePlate", "licensePlate" ], "arguments": null, "defaultMessage": "licensePlate", "code": "licensePlate" }, [], { "defaultMessage": "^[A-ZÖÜÄ]{1,3} [A-ZÖÜÄ]{1,2} [1-9][0-9]{0,3}[E]?$", "arguments": null, "codes": [ "^[A-ZÖÜÄ]{1,3} [A-ZÖÜÄ]{1,2} [1-9][0-9]{0,3}[E]?$" ] } ], "defaultMessage": "must match \"^[A-ZÖÜÄ]{1,3} [A-ZÖÜÄ]{1,2} [1-9][0-9]{0,3}[E]?$\"", "objectName": "addVehicleDto", "field": "licensePlate", "rejectedValue": "1", "bindingFailure": false, "code": "Pattern" } ], "path": "/api/vehicles" }
I've modeled the "standard" error response myself and added the following annotation, but I'm unsure what
implementation
I can use for the validation errors. Those I would probably add withScheme.oneOf
for 400 requests.@PostMapping @ResponseStatus(ACCEPTED) @Operation(summary = "Add vehicle", responses = { @ApiResponse(responseCode = "400", description = "The user provides contradictory organization information", content = @Content(schema = @Schema(implementation = ResponseStatusExceptionResponse.class))), @ApiResponse(responseCode = "403", description = "The user is not allowed to add vehicles")} ) public CompletableFuture<UUID> add
-
Protect Swagger-UI via password in Java/Springboot microservice
I am working on java/springboot micro-services exposing ReST open-apis
For convenience, I embed Swagger-UI in order to allow to easily trigger ReST queries (more precisely, only GET queries)
However, I would like to protect the access to the Swagger-UI by a password stored in the configuration of the micro-service (encrypted or not)
How can I do that?
Thanks for help
-
SpringBoot Rest Controller Supporting both xml and json with JAXB Pojos + Custom Http Message Converters + Swagger-UI
Getting following Swagger error when I introduced custom message converters
Unable to render this definition The provided definition does not specify a valid version field. Please indicate a valid Swagger or OpenAPI version field. Supported version fields are swagger: "2.0" and those that match openapi: 3.0.n (for example, openapi: 3.0.0).
The error is misleading, I guess its getting confused with the converters. Any Ideas to get it fixed?
I followed - swagger-ui not working with custom XML ObjectMapper (no luck)
Background:
I have generated pojos from xsd(s) through xjc. And I have a rest endpoint which needs to support both xml and json for request/response
We got it working by following [spring documentation][1] section: 22.16.12 Message Converters
Here is what I added in MyConfig
@Configuration @EnableWebMvc public class MyConfig implements WebMvcConfigurer { @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { converters.add(new MappingJackson2HttpMessageConverter(objectMapper())); converters.add(new MappingJackson2XmlHttpMessageConverter(xmlMapper())); } @Bean @Primary public ObjectMapper objectMapper() { return new Jackson2ObjectMapperBuilder() .modulesToInstall(new JaxbAnnotationModule()) .build(); } @Bean public XmlMapper xmlMapper() { return new Jackson2ObjectMapperBuilder() .indentOutput(true) .defaultUseWrapper(false) .serializationInclusion(JsonInclude.Include.NON_EMPTY) .modulesToInstall(new JaxbAnnotationModule()) .createXmlMapper(true) .build(); } }
and my controller
// all the open api annotations // @RequestMapping(value = "/run", produces = {"application/json", "application/xml"}, consumes = {"application/json", "application/xml"}, method = RequestMethod.POST) public ResponseEntity<MyResponse> run(@RequestBody MyRequest request) {