I have tried for a couple hours to get this fixed, I keep getting the error:
[Fatal]Error generating client model: Found operation objects with duplicate operationId 'recent_items'. OperationId must be unique among all operations described in the API.
I am using visual studio 2017
Azure SQL database
C#
I cannot see any duplicate operationid in the below (I also cannot seem to format it neatly for here -- very sorry!)
{
"swagger": "2.0",
"info": {
"version": "v1",
"title": "azure_items_API"
},
"host": "azureitemsapi20170719125618.azurewebsites.net",
"schemes": ["http"],
"paths": {
"/api/recent_items": {
"get": {
"tags": ["recent_items"],
"operationId": "recent_items_GetAllrecent_items",
"consumes": [],
"produces": ["application/json",
"text/json",
"application/xml",
"text/xml"],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/recent_items"
}
}
}
},
"deprecated": false
},
"post": {
"tags": ["recent_items"],
"operationId": "recent_items_Postrecent_items",
"consumes": ["application/json",
"text/json",
"application/xml",
"text/xml",
"application/x-www-form-urlencoded"],
"produces": ["application/json",
"text/json",
"application/xml",
"text/xml"],
"parameters": [{
"name": "recent_items",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/recent_items"
}
}],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/recent_items"
}
}
},
"deprecated": false
}
},
"/api/recent_items/{id}": {
"get": {
"tags": ["recent_items"],
"operationId": "recent_items_Getrecent_items",
"consumes": [],
"produces": ["application/json",
"text/json",
"application/xml",
"text/xml"],
"parameters": [{
"name": "id",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/recent_items"
}
}
},
"deprecated": false
},
"put": {
"tags": ["recent_items"],
"operationId": "recent_items_Putrecent_items",
"consumes": ["application/json",
"text/json",
"application/xml",
"text/xml",
"application/x-www-form-urlencoded"],
"produces": [],
"parameters": [{
"name": "id",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
},
{
"name": "recent_items",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/recent_items"
}
}],
"responses": {
"204": {
"description": "No Content"
}
},
"deprecated": false
},
"delete": {
"tags": ["recent_items"],
"operationId": "recent_items_Deleterecent_items",
"consumes": [],
"produces": ["application/json",
"text/json",
"application/xml",
"text/xml"],
"parameters": [{
"name": "id",
"in": "path",
"required": true,
"type": "integer",
"format": "int32"
}],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/recent_items"
}
}
},
"deprecated": false
}
}
},
"definitions": {
"recent_items": {
"type": "object",
"properties": {
"id": {
"format": "int32",
"type": "integer"
},
"item_number": {
"type": "string"
},
"stop_name": {
"type": "string"
},
"stop_address1": {
"type": "string"
}
}
}
}
}
It did have a duplicate get but I changed on of them to a getAll in the controller. Here is the controller in full:
public class recent_itemsController : ApiController
{
private first_choice_itemsEntities db = new first_choice_itemsEntities();
// GET: api/recent_items
public IQueryable<recent_items> GetAllrecent_items()
{
return db.recent_items;
}
// GET: api/recent_items/5
[ResponseType(typeof(recent_items))]
public IHttpActionResult Getrecent_items(int id)
{
recent_items recent_items = db.recent_items.Find(id);
if (recent_items == null)
{
return NotFound();
}
return Ok(recent_items);
}
// PUT: api/recent_items/5
[ResponseType(typeof(void))]
public IHttpActionResult Putrecent_items(int id, recent_items recent_items)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
if (id != recent_items.id)
{
return BadRequest();
}
db.Entry(recent_items).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!recent_itemsExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return StatusCode(HttpStatusCode.NoContent);
}
// POST: api/recent_items
[ResponseType(typeof(recent_items))]
public IHttpActionResult Postrecent_items(recent_items recent_items)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.recent_items.Add(recent_items);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = recent_items.id }, recent_items);
}
// DELETE: api/recent_items/5
[ResponseType(typeof(recent_items))]
public IHttpActionResult Deleterecent_items(int id)
{
recent_items recent_items = db.recent_items.Find(id);
if (recent_items == null)
{
return NotFound();
}
db.recent_items.Remove(recent_items);
db.SaveChanges();
return Ok(recent_items);
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
private bool recent_itemsExists(int id)
{
return db.recent_items.Count(e => e.id == id) > 0;
}
}
I finally had to go back and remove every underscore '_' in my model and controller.
I removed them in the database table name and fields for good measure...I am not sure if that was required.
That is extremely frustrating and a waste of most of what was a good afternoon.
Hope this helps somebody else.
Related
If I have parameter of guid in my webapi action, the swagger UI will validate the format and not let me enter something that doesn't match the guid format.
This is my controller:
[ApiController]
[Route("[controller]")]
public class GuidTestController : ControllerBase
{
private readonly ILogger<GuidTestController> _logger;
public GuidTestController(ILogger<GuidTestController> logger)
{
_logger = logger;
}
[HttpPost("GuidTest")]
public string GuidTest(Guid id)
{
return $"{Request.ContentType}: {Request.ContentLength}";
}
}
This is the generated swagger json:
{
"openapi": "3.0.1",
"info": {
"title": "WebAPI.Test",
"version": "1.0"
},
"paths": {
"/GuidTest/GuidTest": {
"post": {
"tags": [
"GuidTest"
],
"parameters": [
{
"name": "id",
"in": "query",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
},
"application/json": {
"schema": {
"type": "string"
}
},
"text/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
},
"components": { }
}
This all works. if, in the swagger ui I enter a malformed guid, the textbox shakes and makes me correct the value.
I'm trying to create an operation filter that lets me create a multipart request. As a test, one part will be a guid and one part will be binary
It looks like this:
public class MultipartOperationFilter : IOperationFilter
{
/// <summary>
/// Apply the filter to the operation only if it is decorated with the attribute
/// </summary>
/// <param name="operation"></param>
/// <param name="context"></param>
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
operation.RequestBody = new OpenApiRequestBody() { Required = false };
operation.RequestBody.Content.Add("multipart/form-data", new OpenApiMediaType()
{
Schema = new OpenApiSchema()
{
Type = "object",
Properties = new Dictionary<string, OpenApiSchema>()
{
{"a_guid",new OpenApiSchema()
{
Type="string",
Format = "uuid",
Title = "This is a guid"
}
},
{"a_file",new OpenApiSchema()
{
Type="string",
Format = "binary",
Title = "file upload"
}
},
}
}
});
}
}
And my controller action looks like this:
[HttpPost("MultiPartFormData")]
public string MultiPartFormData(Guid id)
{
return $"{Request.ContentType}: {Request.ContentLength}";
}
the resulting swagger.json looks like this:
{
"openapi": "3.0.1",
"info": {
"title": "WebAPI.Test",
"version": "1.0"
},
"paths": {
"/MultipartFilterTest/MultiPartFormData": {
"post": {
"tags": [
"MultipartFilterTest"
],
"parameters": [
{
"name": "id",
"in": "query",
"schema": {
"type": "string",
"format": "uuid"
}
}
],
"requestBody": {
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"properties": {
"a_guid": {
"title": "This is a guid",
"type": "string",
"format": "uuid"
},
"a_file": {
"title": "file upload",
"type": "string",
"format": "binary"
}
}
}
}
}
},
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
},
"application/json": {
"schema": {
"type": "string"
}
},
"text/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
},
"components": { }
}
The swagger ui will create well formed multipart request, but it doesn't validate that the guid value in the first part is formatted correctly, although it does validate that the guid parameter is the correct format. Is this just a shortcoming of either swagger or possible swashbuckle?
I'd like to read an OpenAPI definition from a URL in C# (I'm using .NET Core 3.1). Example definition:
{
"openapi": "3.0.1",
"info": {
"title": "ExampleAPI",
"version": "v1"
},
"paths": {
"/WeatherForecast": {
"get": {
"tags": [
"WeatherForecast"
],
"responses": {
"200": {
"description": "Success",
"content": {
"text/plain": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
},
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
},
"text/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/WeatherForecast"
}
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"WeatherForecast": {
"type": "object",
"properties": {
"date": {
"type": "string",
"format": "date-time"
},
"temperatureC": {
"type": "integer",
"format": "int32"
},
"temperatureF": {
"type": "integer",
"format": "int32",
"readOnly": true
},
"summary": {
"type": "string",
"nullable": true
}
},
"additionalProperties": false
}
}
}
}
I'd like to have a SwaggerDocument that I can parse and read all controller methods, the parameterss for those methods, the models in the response, etc.
I don't have a code sample, I'm really struggling to find any examples of this. Has anyone done something similar? Or have any pointers?
I am new to JsonSchema, I am trying to generate swagger(3.0) JSON. I am using NJsonSchema.
It has successfully generated the JSON schema for models. The only problem is that the JSON has references to the complex type. I tried the generated JSON in http://editor.swagger.io/ and the UI is generated fine, but I have a lot of structural error.
Structural error at paths./xyz/asd/abc/.schema
should NOT have additional properties
additionalProperty: definitions
following is the sample JSON which can be tested on the above link.
{
"openapi": "3.0.1",
"info": {
"title": "SomeTitle",
"description": "someDescription",
"version": "v1"
},
"paths": {
"/Device": {
"get": {
"summary": "someSummary",
"tags": [
"Device"
],
"parameters": [
{
"name": "id",
"in": "query",
"description": "deviceId",
"required": true,
"schema": {
"type": "string",
"nullable": false
}
}
],
"responses": {
"200": {
"description": "Success.",
"content": {
"application/json": {
"schema": {
"title": "SomeTitleAgain",
"type": "object",
"additionalProperties": false,
"required": [
"id"
],
"properties": {
"id": {
"type": "string"
},
"udiCarrier": {
"$ref": "#/paths/~1Device/get/responses/200/content/application~1json/schema/definitions/ListOfUdiCarrierComponent"
}
},
"definitions": {
"ListOfUdiCarrierComponent": {
"type": "array",
"items": {
"$ref": "#/paths/~1Device/get/responses/200/content/application~1json/schema/definitions/UdiCarrierComponent"
}
},
"UdiCarrierComponent": {
"type": "object",
"additionalProperties": false,
"properties": {
"carrierHRF": {
"type": "string"
}}}}}}}}}}}},
"components": { }
}
I don't think NJsonSchema gives a way to get rid of schema reference handling.
So JSON generated always has these references.
Is there any way to process this schema and get the references inline?
I also looked for NewtonsoftJson's IReferenceResolver examples on the internet but could not get a clear picture of how can I use it.
Thanks in Advance.
I have corrected you JSON file with the correct way to use schema and $ref attribute:
{
"openapi": "3.0.1",
"info": {
"title": "SomeTitle",
"description": "someDescription",
"version": "v1"
},
"paths": {
"/Device": {
"get": {
"summary": "someSummary",
"tags": [
"Device"
],
"parameters": [
{
"name": "id",
"in": "query",
"description": "deviceId",
"required": true,
"schema": {
"type": "string",
"nullable": false
}
}
],
"responses": {
"200": {
"description": "Success.",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ListOfUdiCarrierComponent"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"ListOfUdiCarrierComponent": {
"title": "SomeTitleAgain",
"type": "object",
"additionalProperties": false,
"required": [
"id"
],
"properties": {
"id": {
"type": "string"
},
"udiCarrier": {
"type": "array",
"items": {
"$ref": "#/components/schemas/UdiCarrierComponent"
}
}
}
},
"UdiCarrierComponent": {
"type": "object",
"additionalProperties": false,
"properties": {
"carrierHRF": {
"type": "string"
}
}
}
}
}
}
I am building a .NET Webhook following this tutorial, dialogflow fulfillment with c and app engine.
Everything works fine except when I want to set up DailyUpdates with a RegisterUpdate Intent.
When the "setup_notification_update" intent calls the webhook I sendthis kind of JSON in response:
{
"fulfillmentText": "Notifica programmata",
"fulfillmentMessages": [
{
"card": {
"title": "Notifica programmata",
"subtitle": "Notifica programmata con successo",
"imageUri": "https://assistant.google.com/static/images/molecule/Molecule-Formation-stop.png",
"buttons": [
{
"text": "Valutami",
"postback": "https://macoev.com/"
}
]
}
}
],
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Questa รจ la risposta di avvenuto successo per la programmazione della notifica"
}
}
]
},
"systemIntent": {
"intent": "actions.intent.REGISTER_UPDATE",
"data": {
"#type": "type.googleapis.com/google.actions.v2.RegisterUpdateValueSpec",
"intent": "get_stats_notification",
"arguments": [
{
"name": "category",
"textValue": "Daily_lowest_temperature"
}
],
"triggerContext": {
"timeContext": {
"frequency": "DAILY"
}
}
}
}
}
}
}
The problem is that the intent that has REGISTER_UPDATE as its event does not get triggered, resulting in the notification not being scheduled.
This is the response that I set when that event get triggered:
{
"responseId": "",
"queryResult": {
"queryText": "",
"action": "",
"parameters": {},
"allRequiredParamsPresent": true,
"fulfillmentText": "",
"fulfillmentMessages": [],
"outputContexts": [],
"intent": {
"name": "finish_update_setup",
"displayName": "finish_update_setup"
},
"intentDetectionConfidence": 1,
"diagnosticInfo": {},
"languageCode": ""
},
"originalDetectIntentRequest": {
"source": "google",
"version": "2",
"payload": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
},
"inputs": [
{
"rawInputs": [],
"intent": "",
"arguments": [
{
"name": "REGISTER_UPDATE",
"extension": {
"#type": "type.googleapis.com/google.actions.v2.RegisterUpdateValue",
"status": "OK"
}
},
{
"name": "text",
"rawText": "04:10pm",
"textValue": "04:10pm"
}
]
}
],
"user": {},
"conversation": {},
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
}
]
}
},
"session": ""
}
Any idea why? Any help will be appreciated. Thanks in advance.
I'm trying to use NEST to create an index with raw json and it produces different results than when I use that same json string interactively against elastic search. Is this a bug or am I using it incorrectly?
Posting directly to elastic search with the following command I get exactly the mappings I want for my index (results shown below)
POST /entities
{
"mappings": {
"sis_item" :
{
"properties":
{
"FullPath":
{
"type": "string",
"index":"not_analyzed"
},
"Ident":
{
"type": "nested",
"properties":
{
"ObjectGuid":
{
"type": "string",
"index":"not_analyzed"
}
}
}
}
}
}
Result when I check the index with: GET /entities/ : (which is correct)
{
"entities": {
"aliases": {},
"mappings": {
"sis_item": {
"properties": {
"FullPath": {
"type": "string",
"index": "not_analyzed"
},
"Ident": {
"type": "nested",
"properties": {
"ObjectGuid": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
},
"settings": {
"index": {
"creation_date": "1453828294488",
"number_of_shards": "5",
"number_of_replicas": "1",
"version": {
"created": "1070499"
},
"uuid": "6_j4vRcqRwiTQw0E6bQokQ"
}
},
"warmers": {}
}
}
However I have to do this from code and using the following code the mappings I specify end up in the settings instead of the mappings as shown below.
var createIndexJson = #"
{
""mappings"": {
""sis_item"" :
{
""properties"":
{
""FullPath"":
{
""type"": ""string"",
""index"":""not_analyzed""
},
""Ident"":
{
""type"": ""nested"",
""properties"":
{
""ObjectGuid"":
{
""type"": ""string"",
""index"":""not_analyzed""
}
}
}
}
}
}
}";
var response = _client.Raw.IndicesCreatePost("entities_from_code", createIndexJson);
if (!response.Success || response.HttpStatusCode != 200)
{
throw new ElasticsearchServerException(response.ServerError);
}
Result (not correct, notice the mappings are nested inside the settings):
{
"entities_from_code": {
"aliases": {},
"mappings": {},
"settings": {
"index": {
"mappings": {
"sis_item": {
"properties": {
"FullPath": {
"type": "string",
"index": "not_analyzed"
},
"Ident": {
"type": "nested",
"properties": {
"ObjectGuid": {
"type": "string",
"index": "not_analyzed"
}
}
}
}
}
},
"creation_date": "1453828283162",
"number_of_shards": "5",
"number_of_replicas": "1",
"version": {
"created": "1070499"
},
"uuid": "fdmPqahGToCJw_mIbq0kNw"
}
},
"warmers": {}
}
}
There is a newline at the very top of the json string which cause the odd result, removing it gave me the expected behaviour.