Resource Not Found Azure Cosmos DB - c#

Hi We are facing issue while querying . The document exists in the database.
"Message: {\"Errors\":[\"Resource Not Found\"]}\r\nActivityId:
03866338-6596-49b6-8704-1726cb373bfb, Request URI:
/apps/ab277caf-ee90-4cc3-96cb-4d4ec5ae2b13/services/17e48284-a3a0-40c5-b5ec-40bd3f207472/partitions/27cb7777-5add-4f72-8a73-1fc8fe34e7bf/replicas/131603393672093060p/,
RequestStats: , SDK: Microsoft.Azure.Documents.Common/1.19.162.2"
Document in Database
{
"consumername": "testconsumer",
"tablename": "Table1",
"securityaccount": "v-naagga",
"logtime": "2018-01-13T21:42:21.3040338-08:00",
"securitydefinition": {
"tablename": "table1",
"ColumnList": {
"columnname": "name",
"columndatatype": "string"
},
"RowSecurity": {
"columnname": "address",
"operator": "operator",
"condition": "somecondition"
}
},
"id": "15554839-096d-4072-8f38-af2e9c64b452",
"_rid": "LmUiAONSDQQBAAAAAAAAAA==",
"_self": "dbs/LmUiAA==/colls/LmUiAONSDQQ=/docs/LmUiAONSDQQBAAAAAAAAAA==/",
"_etag": "\"00002e04-0000-0000-0000-5a5aedd60000\"",
"_attachments": "attachments/",
"_ts": 1515908566
}
Below is the update method code which is throwing this Error
{
try
{
RequestOptions options = new RequestOptions();
options.PartitionKey = new PartitionKey(id);
options.ConsistencyLevel = ConsistencyLevel.Session;
return await client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(DatabaseId, SecurityCollectionId, id), item,options).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger.Log(ErrorLevel.Error, ex.Message);
throw ex;
}
}

According to my observations, I think your issue should be partition key settings error.
Please refer to this official document.You need to provide the value of the partition key, not the name of the field which stores the partition key.
For example , my container is created like this:
The partition key is "name" for my collection here. You could check your collection's partition key.
And my documents as below :
{
"id": "1",
"name": "jay"
}
{
"id": "2",
"name": "jay2"
}
My partitionkey is 'name', so here I have two paritions : 'jay' and 'jay1'.
So, here you should set the partitionkey property to 'jay' or 'jay2',not 'name'.
try
{
RequestOptions options = new RequestOptions();
options.PartitionKey = new PartitionKey("jay");
options.ConsistencyLevel = ConsistencyLevel.Session;
return await client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(DatabaseId, SecurityCollectionId, id), item,options).ConfigureAwait(false);
}
catch (Exception ex)
{
Logger.Log(ErrorLevel.Error, ex.Message);
throw ex;
}
Hope it helps you.
Update Answer :
I created a sample document as same as yours and replaced it successfully.
Please refer to my test code.
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
using System;
using System.Linq;
namespace ConsoleApp2
{
class Program
{
private static DocumentClient client;
static string endpoint = "***";
static string key = "***";
static string database = "***";
static string collection = "***";
static void Main(string[] args)
{
client = new DocumentClient(new Uri(endpoint), key);
try
{
Sample querysample = client.CreateDocumentQuery<Sample>(
UriFactory.CreateDocumentCollectionUri(database, collection))
.Where(so => so.id == "1")
.AsEnumerable()
.First();
Console.WriteLine(querysample.tablename);
querysample.tablename = "Table2";
RequestOptions options = new RequestOptions();
options.PartitionKey = new PartitionKey("1");
options.ConsistencyLevel = ConsistencyLevel.Session;
var result = client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(database, collection, "1"), querysample, options).Result;
}
catch (Exception ex)
{
throw ex;
}
Console.ReadLine();
}
}
public class Sample
{
public string id { get; set; }
public string tablename { get; set; }
}
}
id is my partition key and the value is '1'. Would you please check the differences between our codes?
If any concern , please let me know.

In my case it was something basic, I had the container name spelt incorrectly. If you are getting a 404 worth checking you are indeed calling the right database and container

Related

Is there a way for get NSwag Swagger to generate a client that can consume IAsyncEnumerable endpoint?

I have an endpoint that returns an IAsyncEnumerable
[HttpPost("GetByDates")]
[ProducesResponseType(typeof(IAsyncEnumerable<DayModel>), StatusCodes.Status200OK)]
public async IAsyncEnumerable<DayModel> GetByDates([FromBody] DayModelGetByDatesRequest request)
{
await foreach (var dayModel in _dayService.GetAsync(request.channelGuid, request.dates.ToArray(), request.onlyPublished, request.IncludeDiscardedScheduledItems))
{
yield return dayModel;
};
}
The generated .json schema looks like this:
"/Private/Days/GetByDates": {
"post": {
"tags": [
"Days"
],
"operationId": "Days_GetByDates",
"requestBody": {
"x-name": "request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/DayModelGetByDatesRequest"
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": "",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Day"
}
}
}
}
}
}
}
}
and the Nswag is configured like this:
services.AddOpenApiDocument(configure =>
{
configure.Title = "MyAppName (Private)";
configure.DocumentName = "private";
configure.SchemaType = SchemaType.OpenApi3;
configure.SchemaNameGenerator = new CustomNameGenerator();
configure.AddOperationFilter(new RequireUserHeaderParameterFilter().Process);
configure.AddSecurity("Bearer", new OpenApiSecurityScheme()
{
In = OpenApiSecurityApiKeyLocation.Header,
Description = "Please enter the word \"Bearer\" followed by space and token",
Name = "Authorization",
Type = OpenApiSecuritySchemeType.ApiKey,
});
configure.ApiGroupNames = new string[] { "Private" };
});
And another project uses the .json schema to genereate a client of its own that seems to use Newtonsoft Json instead of System.Text.Json
[System.CodeDom.Compiler.GeneratedCode("NSwag", "13.18.0.0 (NJsonSchema v10.8.0.0 (Newtonsoft.Json v13.0.0.0))")]
public partial class TablaApiClient
{
private string _baseUrl = "https://localhost:5102";
private System.Net.Http.HttpClient _httpClient;
private System.Lazy<Newtonsoft.Json.JsonSerializerSettings> _settings;
public TablaApiClient(System.Net.Http.HttpClient httpClient)
{
_httpClient = httpClient;
_settings = new System.Lazy<Newtonsoft.Json.JsonSerializerSettings>(CreateSerializerSettings);
}
private Newtonsoft.Json.JsonSerializerSettings CreateSerializerSettings()
{
var settings = new Newtonsoft.Json.JsonSerializerSettings();
UpdateJsonSerializerSettings(settings);
return settings;
}
public string BaseUrl
{
get { return _baseUrl; }
set { _baseUrl = value; }
}
protected Newtonsoft.Json.JsonSerializerSettings JsonSerializerSettings { get { return _settings.Value; } }
partial void UpdateJsonSerializerSettings(Newtonsoft.Json.JsonSerializerSettings settings);
The endpoint doesn't serialize the IAsyncEnumerable and return an ICollection instead:
The Swagger is configured like so:
services.AddOpenApiDocument(configure =>
{
configure.Title = "My App";
configure.SchemaType = NJsonSchema.SchemaType.OpenApi3;
configure.AddSecurity("AzureAsIdentityProvider", new OpenApiSecurityScheme
{
Type = OpenApiSecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
AuthorizationCode = new OpenApiOAuthFlow
{
AuthorizationUrl = $"{settings.Instance}/{settings.TenantId}/oauth2/v2.0/authorize",
TokenUrl = $"{settings.Instance}/{settings.TenantId}/oauth2/v2.0/token",
}
}
});
configure.OperationProcessors.Add(new AspNetCoreOperationSecurityScopeProcessor("AzureAsIdentityProvider"));
});
Is there a way for the generated client to properly serialize and understand it is working towards an IAsyncEnumerable endpoint so that I can work with the stream instead of fully buffered collection?
I read that System.Text.Json serializes IAsyncEnumerable out of the box. Is there a way to get Swagger to use that instead of Newtonsoft?

C# Update Azure Cosmos Db json item with Upsert

I'm (new to CosmosDb) and trying to update an item in an Azure Cosmos db, but it's inserting instead.
The object sent is
public class Bank
{
public string id { get; set; }
public string Code { get; set; }
public string Name { get; set; }
}
I tried passing only the Code and the Name values back (i.e. I did not include the id in the object, which causes an insert (I wanted an update).
I am now including the id which results in an error.
Error returned is:
ResourceType Document is unexpected.
ActivityId: a0d50426-c556-4b17-9646-93052699026e, Windows/10.0.19044 documentdb-netcore-sdk/2.16.2
So, it's values after a front end update (only changing the Name value) are:
Code: "FNB"
Name: "aa First Update Test"
id: "d76ade3d-7d02-46e5-a458-e9f0781bf044"
The DAL code:
var documentUri = UriFactory.CreateDocumentUri(DBName, "Banks", bank.Code);
try
{
Document doc = await client.UpsertDocumentAsync(documentUri, bank);
}
How do I get it to update?
TIA
Your Code is not clear and dont have enough information.try these functions.
protected DataContext(string endpointUrl, string databaseId,
string masterKey)
{
_databaseId = databaseId;
_masterKey = masterKey;
_databaseUri = UriFactory.CreateDatabaseUri(_databaseId);
this._client = new DocumentClient(new Uri(endpointUrl), _masterKey);
this._client.CreateDatabaseIfNotExistsAsync(new Database
{ Id = _databaseId });
this._client.CreateDocumentCollectionIfNotExistsAsync(
UriFactory.CreateDatabaseUri(_databaseId),
new DocumentCollection { Id = CollectionId });
_databaseCollectionUri = UriFactory.CreateDocumentCollectionUri(
_databaseId, CollectionId);
}
insert and update using
public async Task<Document> UpsertDocumentAsync(T entity)
{
var result = await this._client.UpsertDocumentAsync(
_databaseCollectionUri, entity);
return result;
}
Or Try please using the nuget Microsoft.Azure.Cosmos;
string cosmosDbConnectionString = CosmosDbConnectionKey;
CosmosClient cosmosClient = new CosmosClient(cosmosDbConnectionString);
var db = CosmosDbNameKey;
var container = ContainerKey;
await container.UpsertItemAsync(Model, new PartitionKey(Model.PK));
What I needed was the DocumentCollection (DocumentCollection Link) in the Upsert, but I had the Document Link (documentUri)
So,
public async Task<ExBool> UpdateAsyncPOCO(Bank bank)
{
// NB: UpsertDocumentAsync should take the DocumentCollection link, instead of Document link.
// This is a DocumentLink
var documentUri = UriFactory.CreateDocumentUri(DBName, "Banks", bank.Code);
// This is a DocumentCollection
var CollectionUri = UriFactory.CreateDocumentCollectionUri("demo", "Banks");
try
{
Document doc = await client.UpsertDocumentAsync(CollectionUri, bank);
}
catch (Exception ex)
{
HandleException(ex);
}
return result;
}
Insert and update work perfectly now.
The model and values for the update:
Code: "updated FNB 2"
Name: "updated First National Bank 22"
id: "d76ade3d-7d02-46e5-a458-e9f0781bf044"
Similarly, the Insert
Code: "qwerty"
Name: "qwertyuiop"
id: ""

HTTP client method null exception

I have an API project and I need to develop a web project using the API I wrote some code but not able to find the exception and problem and not getting data from the link.
Here is my Service Code:
public async Task<IEnumerable<AgentReadDto>> GetAgent()
{
IEnumerable<AgentReadDto> agents = new List<AgentReadDto>();
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://localhost:44331/api/");
var response = client.GetAsync("Agent/GetAllAgent");
response.Wait();
var result = response.Result;
if (result.IsSuccessStatusCode)
{
var readTask =JsonConvert.DeserializeObject<IList<AgentReadDto>>(await result.Content.ReadAsStringAsync());
agents = readTask;
}
}
return agents;
}
And my controller code is look like this:
public IActionResult AgentLists()
{
var agentsList = _agentRespositoryWeb.GetAgent();
if (agentsList != null )
{
ViewBag.Message = "There was a problem retrieving agent from the database or no agents exists";
}
ViewBag.SuccessMessage = TempData["SuccessMessage"];
return View(agentsList);
}
My api return the value following:
{
"agentDetail": [
{
"usersId": 85,
"firstName": "Amit",
"lastName": "One",
"gender": "Male",
"informationTips": [
{
"video": "https://www.w3schools.com/html/movie.mp4"
},
{
"video": "https://www.w3schools.com/html/movie.mp4"
},
]
},
{
"usersId": 86,
"firstName": "Amit",
"lastName": "Two",
"gender": "Male",
"informationTips": [
{
"video": "https://www.w3schools.com/html/movie.mp4"
}
]
}
]
}
For exception I added image there is three image that take screen on the different steps:
Your model is set to IEnumerable<AgentReadDto>, but you've forgotten to await the call to GetAgent inside of the AgentLists action. This means there's a mismatch between what the view expects (IEnumerable<AgentReadDto>) and what it receives (Task<IEnumerable<AgentReadDto>>).
To fix this, convert AgentLists to an async method and then await the call to GetAgent. Here's a fixed version of the AgentLists action:
public async Task<IActionResult> AgentLists()
{
var agentsList = await _agentRespositoryWeb.GetAgent();
if (agentsList != null)
{
ViewBag.Message =
"There was a problem retrieving agent from the database or no agents exists";
}
ViewBag.SuccessMessage = TempData["SuccessMessage"];
return View(agentsList);
}
It looks like you also have a mismatch between the type you expect to be returned and the JSON actually being returned. The JSON represents an object with a list inside of it, but you're attempting to parse it as a simple list. To fix that, create a wrapper class that matches the structure of the response. For example, create the following class:
public class ApiResponse
{
public IEnumerable<AgentReadDto> AgentDetail { get; set; }
}
Update the deserialization logic to use this new type:
var apiResponse = JsonConvert.DeserializeObject<ApiResponse>(...);
var agentsLit = apiResponse.AgentDetail;

ASP.NET Core empty validation string entry in array of errors?

When we have an action, accepting the following argument:
[FromBody][Range(1, 10)] int hello
When validation fails, the object returned has an empty entry, like so:
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "|3b00401-417ccac45f29647d.",
"errors": {
"": [
"hello is required."
]
}
}
Why is that? Could you refer to the source which is causing this problem? I believe it's tied with reflection, i.e they get the object's properties, but in our case it's a simple int/string object, not a custom type.
Firstly,you can refer to this
and you can see the default BadRequest response:
errors": {
"": [
"A non-empty request body is required."
]
It should be "number": [ "The field number...." but right now it's "" : [ "The field number...,so the response is a default response format.
And if you want to custom errors,you can do like this:
public class CustomBadRequest : ValidationProblemDetails
{
public CustomBadRequest(ActionContext context)
{
Title = "Invalid arguments to the API";
Detail = "The inputs supplied to the API are invalid";
Status = 400;
ConstructErrorMessages(context);
Type = context.HttpContext.TraceIdentifier;
}
private void ConstructErrorMessages(ActionContext context)
{
var reader = new StreamReader(context.HttpContext.Request.Body);
var body = reader.ReadToEndAsync();
foreach (var keyModelStatePair in context.ModelState)
{
var key = keyModelStatePair.Key;
if (key == "")
{
Errors.Add("number", new string[] { "nmber is not between 1,10" });
}
else
{
Errors.Add("number", new string[] { "this is not number" });
}
}
}
string GetErrorMessage(ModelError error)
{
return string.IsNullOrEmpty(error.ErrorMessage) ?
"The input was not valid." :
error.ErrorMessage;
}
}
Modify in Startup.cs
services.AddControllersWithViews()
.ConfigureApiBehaviorOptions(options=>
{
options.InvalidModelStateResponseFactory = contet =>
{
var problems = new CustomBadRequest(contet);
return new BadRequestObjectResult(problems);
};
});
result:
You can achieve this by using the ModelBinder attribute.
For example:
[ModelBinder(Name = "number")]

Adding record to Zoho creator

Hi I am using following code to add a record to Zoho Creator form using asp.net c#.
However I receive in respose "The form has been removed from publish."
I have checked form at Zoho creator its working fine & has been published.
Please help me figure out the problem.
public partial class WebForm1 : System.Web.UI.Page
{
protected void btnSubmit_OnClick(object sender, EventArgs e)
{
var response = Http.Post("https://creator.zoho.com/saadelboury1/myfirstApp/form-perma/NEWDISTRIBUTOR/record/add/", new NameValueCollection() {
{ "authtoken", "<KEY>" },
{ "scope", "creatorapi" },
{ "First_Name", "John" },
{ "Last_Name", "Doe" },
{ "Email", "someone22#gmail.com" },
});
string result = System.Text.Encoding.UTF8.GetString(response);
Response.Write(result);
}
}
}
public static class Http
{
public static byte[] Post(string uri, NameValueCollection pairs)
{
byte[] response = null;
using (WebClient client = new WebClient())
{
response = client.UploadValues(uri, pairs);
}
return response;
}
Turned out, the url I was calling was wrong.
The correct url format is:
https://creator.zoho.com/api/[username]/xml/[application_name]/form/[form_name]/record/add/
Here I push the records from the school form to the student form with the help of add record task.
var = Insert into Student
[
Name = input.Name
Email = input.Email
Phone = input.Phone
Address = input. Address
];
Variable holding the ID of the new record.
<<form_link_name> Link name of the field for which the value is specified.
Value to be assigned to the field. You can directly specify a value, or you can specify an expression.

Categories