I'm new to ASP.NET MVC and have an existing API which returns JSON. This API exists on another server and I need to make a server-to-server call to API and bind the resultant data to a Model so that it can be used within other parts of this web app I'm making.
I tried searching for this and it seems like it exists but I can't find the basic documentation for it or how to implement it.
I could make each component (make HTTP request, parse the JSON, set a model to use the data), but I'd hate to re-invent the wheel (and probably do it poorly) if this is something that is already in the library.
Example of the API call:
http://example.info/feeds/feed.aspx?alt=json-in-script
response:
{
"version": "1.0",
"encoding": "UTF-8",
"feed": {
"updated": {
"$t": "2014-07-08T13:58:21-05:00"
},
"id": {
"$t": "http://example.info/feeds/feed.aspx"
},
"title": {
"type": "text",
"$t": "Example Calendar of Events"
},
"link": [
{
"rel": "alternate",
"type": "text/html",
"href": "http://feed.example.edu/search/"
},
{
"rel": "alternate",
"type": "application/json",
"title": "JSON",
"href": "http://example.info/feeds/feed.aspx?alt=json"
},
{
"rel": "alternate",
"type": "text/calendar",
"title": "iCal",
"href": "http://example.info/feeds/feed.aspx?alt=ical"
},
{
"rel": "self",
"type": "application/atom+xml",
"title": "ATOM Feed",
"href": "http://example.info/feeds/feed.aspx"
}
],
"author": [
{
"name": {
"$t": "Example!!"
},
"email": {
"$t": "web#example.edu"
}
}
],
"gd$where": [
{
"valueString": "Chicago, IL, US"
}
],
"gCal$timezone": {
"value": "America/Chicago"
},
"entry": [
{
"category": [
{
"scheme": "http://schemas.google.com/g/2005#kind",
"term": "http://schemas.google.com/g/2005#event"
},
{
"term": "Current Students"
},
{
"term": "Faculty"
},
{
"term": "Staff"
}
],
"published": {
"$t": "2012-03-06T20:57:24+00:00"
},
"updated": {
"$t": "2012-03-06T20:57:24+00:00"
},
"id": {
"$t": "http://example.info/feed/?eventid=74289"
},
"gCal$uid": {
"value": "e72724e9-34eb-41dd-a75a-78d1577cb98a.127924#feed.example.edu"
},
"title": {
"type": "text",
"$t": "Last Day of Sessions 1 & 4 Classes"
},
"content": {
"type": "html",
"$t": "<p>Session 1 & 4 period ends today.</p>"
},
"summary": {
"type": "text",
"$t": "Session 1 & 4 period ends today."
},
"author": [
{
"name": {
"$t": "Office"
},
"email": {
"$t": "registrar#example.edu"
}
}
],
"gd$who": [
{
"rel": "http://schemas.google.com/g/2005#event.organizer",
"valueString": "Registrar, Office of the"
},
{
"rel": "http://schemas.google.com/g/2005#event.attendee",
"valueString": "Current Students"
},
{
"rel": "http://schemas.google.com/g/2005#event.attendee",
"valueString": "Faculty"
},
{
"rel": "http://schemas.google.com/g/2005#event.attendee",
"valueString": "Staff"
}
],
"gd$organization": [
{
"label": "Campus",
"primary": "true",
"gd$orgName": {
"$t": "Chicago"
}
}
],
"gd": {
"value": "http://schemas.google.com/g/2005#event.opaque"
},
"link": [
{
"rel": "alternate",
"type": "text/html",
"href": "http://feed.example.edu/viewevent.aspx?eventid=74289&occurrenceid=127924"
}
],
"gCal$sequence": {
"value": "0"
},
"gd$when": [
{
"startTime": "2014-07-30",
"endTime": "2014-07-31"
}
],
"gd$where": [
{
"valueString": "Classes administered by the Chicago Campus"
}
]
},
...
]
}
}
Edit:
I just now found this article on Calling a Web API From a .NET Client, which is in-line with what I'm trying to ask with this question, but I need to know how to do this in an ASP.NET MVC context, not a console application.
To call an external API you can use the HttpClient. Personally, I would wrap the calls to the API in their own class akin to the repository pattern.
public class ApiCaller
{
/*
this is the repository that can wrap calls to the API
if you have many different types of object returned
from the API it's worth considering making this generic
*/
HttpClient client;
public SomeClass Get()
{
SomeClass data;
string url = "http://example.info/feeds/feed.aspx?alt=json-in-script";
using (HttpResponseMessage response = client.GetAsync(url).Result)
{
if (response.IsSuccessStatusCode)
{
data = JsonConvert.DeserializeObject<SomeClass>(response.Content.ReadAsStringAsync().Result);
}
}
return data;
}
}
Then in the controller I would call the ApiCaller to get the object required at which point in this instance I'm just passing it to a view:
public class MyController : Controller
{
ApiCaller caller;
public MyController()
{
//maybe inject this dependency
ApiCaller = new ApiCaller();
}
public ActionResult Index()
{
SomeClass model = ApiCaller.Get();
//do something with the instance if required
return View(model);
}
}
The ApiCaller can then be extended if required to support posts, puts etc. If you have many different entities on the API that you wish to handle you can make an ApiCaller per entity or you could potentially use generics.
You must change from ActionResult to JsonResult. Also you can create a derived class as I did or use native class JsonResult.
public JsonResult CheckTimeout()
{
return Json(new JsonReturn { Success = true, ResponseData = new object() });
}
[Serializable]
public class JsonReturn : JsonResult
{
public JsonReturn()
{
Success = true;
Message = string.Empty;
ResponseData = null;
}
public JsonReturn(object obj)
{
Success = true;
Message = string.Empty;
ResponseData = obj;
}
public bool Success { get; set; }
public string Message { get; set; }
public object ResponseData { get; set; }
}
}
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 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.
My C# web API has successfully received a request from my Actions on google dialog flow. But I am having issues understanding what the response format should be.
{
"responseId": "96ee6c11-8f73-409f-8dac-8b6141d08483",
"queryResult": {
"queryText": "History",
"action": "tell.fact",
"parameters": {
"category": "history"
},
"allRequiredParamsPresent": true,
"fulfillmentMessages": [
{
"text": {
"text": [
""
]
}
}
],
"outputContexts": [
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/google_assistant_input_type_touch",
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/actions_capability_screen_output",
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/choose_fact-followup",
"lifespanCount": 2,
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/actions_capability_audio_output",
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/actions_capability_media_response_audio",
"parameters": {
"category.original": "History",
"category": "history"
}
},
{
"name": "projects/project--6162817918903295576/agent/sessions/1530877719318/contexts/actions_capability_web_browser",
"parameters": {
"category.original": "History",
"category": "history"
}
}
],
"intent": {
"name": "projects/project--6162817918903295576/agent/intents/4a35cf33-e446-4b2b-a284-c70bc4dfce17",
"displayName": "choose_fact"
},
"intentDetectionConfidence": 1,
"languageCode": "en-us"
},
"originalDetectIntentRequest": {
"source": "google",
"version": "2",
"payload": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
},
"requestType": "SIMULATOR",
"inputs": [
{
"rawInputs": [
{
"query": "History",
"inputType": "TOUCH"
}
],
"arguments": [
{
"rawText": "History",
"textValue": "History",
"name": "text"
}
],
"intent": "actions.intent.TEXT"
}
],
"user": {
"lastSeen": "2018-07-06T11:44:24Z",
"locale": "en-US",
"userId": "AETml1TDDPgKmK2GqQ9ugHJc5hQM"
},
"conversation": {
"conversationId": "1530877719318",
"type": "ACTIVE",
"conversationToken": "[]"
},
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
}
]
}
},
"session": "projects/project--6162817918903295576/agent/sessions/1530877719318"
}
attempt one
The documentation webhook states that my response should look like that
{"fulfillmentText":"Hello from C# v2","fulfillmentMessages":[{"card":{"title":"card title","subtitle":"sub title","imageUri":"https://assistant.google.com/static/images/molecule/Molecule-Formation-stop.png","buttons":[{"text":"button text","postback":"https://assistant.google.com/"}]}}],"source":"example.com","payload":{"google":{"expectUserResponse":true,"richResponse":{"items":[{"simpleResponse":{"textToSpeech":"Thi sis a simple response "}}]}},"facebook":{"text":"Hello facebook"},"slack":{"text":"Hello facebook"}},"outputContexts":[{"name":"projects/project--6162817918903295576/agent/sessions/2a210c67-4355-d565-de81-4d3ee7439e67","lifespanCount":5,"parameters":{"param":"parm value"}}],"followupEventInput":{"name":"event name","languageCode":"en-Us","parameters":{"param":"parm value"}}}
This results in the following error
MalformedResponse 'final_response' must be set.
Failed to parse Dialogflow response into AppResponse because of empty speech response
attempt 2
So i went on to try simple response
{
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "this is a simple response"
}
}
]
}
}
}
}
Which also results with
MalformedResponse 'final_response' must be set.
Failed to parse Dialogflow response into AppResponse because of empty speech response
I can verify that my requests are being sent as application/json
Does anyone know the proper response format?
The root problem is actually ASP.NET Core by default uses transfer-encoding: chunked for ActionResult and for some reason Dialogflow does not support parsing chunked transfer
The following response is accepted by actions.
[HttpPost]
public ContentResult Post([FromBody] FulfillmentRequst data)
{
var response = new FulfillmentResponse
{
fulfillmentText = "Hello from C# v2",
};
return Content(JsonConvert.SerializeObject(response), "application/json");
}
Here is the JSON response format: https://github.com/dialogflow/fulfillment-webhook-json/blob/master/responses/v2/response.json
I have lots of product typed documents saved in elasticsearch but couldn't search by documents property values and need help.
//Product Class
public Guid productID { get; set; }
public string productName { get; set; }
public Guid productTypeID { get; set; }
public List<Guid> categoryIds {get; set; }
I'm trying to search like this:
//Search function
var esconn = Yaziylabir.Bukalemun.DataObjects.ElasticSearchConnectionManager.GetClient();
QueryContainer q = null;
if (!ProductType.HasValue || (ProductType.HasValue && ProductType.Value == B2CVariables.PRODUCTTYPE_PRODUCT))
{
q = Query<ProductModel>.Term(t => t.ProductTypeID, B2CVariables.PRODUCTTYPE_PRODUCT);
}
if (Category != null)
{
//catListZ is also List<Guid>
q &= Query<ProductModel>.Terms(u=>u.Field(z=>z.CategoryIDs).Terms<Guid>(catListZ));
}
// as a bonus I also have keyword search
if (!string.IsNullOrEmpty(Keyword))
{
q &= Query<ProductModel>.QueryString(t => t.Query(Keyword));
}
//do search
var pp = new SearchRequest(Yaziylabir.Bukalemun.DataObjects.ElasticSearchConnectionManager.DefaultIndex, "product");
pp.Query = q;
pp.Size = PageSize;
var res = esconn.Search<ProductModel>(pp);
rtnVal = res.Documents.ToList();
Now, I tried combinations of these (only producttypeID, only categoryIDs, only keyword, etc...) and watch what is happening with fiddler.
No result comes back, no errors are raised. Only 0 hits. Request body seems ok too.
When I check documents stored in that index, they are there and they have values required and should return in result.
What is wrong here? Do you have any ideas? Please help me here. I'm feeling ashamed to be the guy who couldn't search a database properly.
EDIT:
Search's body text:
{"size":12,"query":{"term":{"productTypeID":{"value":"cae344cf-8cfa-4960-8387-8ee89899c53f"}}}}
Example document:
{
"productID": "5687b8ac-c3fe-4f1a-9643-08b0bf6cede8",
"productName": "7011 Yelek",
"productCode": "701102Y001 ",
"currency": {
"currencyID": 1,
"sign": "TL",
"rate": 0
},
"normalPrice": 170,
"currentPrice": 84.9,
"isDiscounted": true,
"taxRate": 8,
"productTypeID": "cae344cf-8cfa-4960-8387-8ee89899c53f",
"defaultImagePath": "/contents/images/productimages/75681ee4-19b3-4c7d-a24b-b3566085a980.jpg",
"totalStockCount": 8,
"totalStockRecordCount": 4,
"isInStock": true,
"statusID": "9ad17471-2ff2-4eb0-9cb0-4b86922263ea",
"categoryIDs": [
"a8c83f54-b784-4866-89c3-cabc641490d5",
"9d5a9ab7-8edb-4d5a-800b-c48bf6575d78"
]
}
I didn't include all properties because it will make document very long.
Here is the mapping:
{
"mappings": {
"product": {
"properties": {
"categoryIDs": {
"type": "string"
},
"currentPrice": {
"type": "double"
},
"isDiscounted": {
"type": "boolean"
},
"isInStock": {
"type": "boolean"
},
"normalPrice": {
"type": "double"
},
"productCode": {
"type": "string"
},
"productID": {
"type": "string"
},
"productName": {
"type": "string"
},
"productTypeID": {
"type": "string"
},
"statusID": {
"type": "string"
},
"taxRate": {
"type": "double"
},
"totalStockCount": {
"type": "long"
},
"totalStockRecordCount": {
"type": "long"
}
}
}
}
}
I suspect the productTypeID field is using either the default analyzer - standard - or any other analyzer that's splitting it in the wrong places. What you need is for productTypeID to be index: not_analyzed or analyzed with something like keyword. And you need to create the mapping manually, otherwise you can't do it the way you want it.
The idea is that ES is tokenizing by default your productTypeID values and will split them at -, so in the index you'd have tokens not the entire value. You, instead, need to have that value unchanged so that term will match it fully.
For example, not to mess up with your previous mapping, you can add fields to define a sub-field that will be not_analyzed:
"productTypeID": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
}
And your query needs to change slightly: {"size":12,"query":{"term":{"productTypeID.raw":{"value":"cae344cf-8cfa-4960-8387-8ee89899c53f"}}}}
For completeness sake, this is the complete command to create the mapping by hand. You could do it while the index is still "alive", but you'd still have to re-index the documents:
curl -XPUT "http://localhost:9200/your_index" -d'
{
"mappings": {
"product": {
"properties": {
"categoryIDs": {
"type": "string"
},
"currentPrice": {
"type": "double"
},
"isDiscounted": {
"type": "boolean"
},
"isInStock": {
"type": "boolean"
},
"normalPrice": {
"type": "double"
},
"productCode": {
"type": "string"
},
"productID": {
"type": "string"
},
"productName": {
"type": "string"
},
"productTypeID": {
"type": "string",
"fields": {
"raw": {
"type": "string",
"index": "not_analyzed"
}
}
},
"statusID": {
"type": "string"
},
"taxRate": {
"type": "double"
},
"totalStockCount": {
"type": "long"
},
"totalStockRecordCount": {
"type": "long"
}
}
}
}
}'
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.