ReplaceDocumentCollectionAsync throwing DocumentClientException - azure-cosmosdb

Trying to update the IndexingPolicy of a collection. The collection definition works fine when using CreateDocumentCollectionIsNotExistsAsync, but when trying to update the definition of an exising collection using ReplaceDocumentCollectionAsync, a DocumentClientException is thrown. using .NET library 1.19.1. Exception details are:
DocDBTrace Error: 0 : DocumentClientException with status code NotFound, message: The value '' specified for query '$resolveFor' is invalid., inner exception: null, and response headers: null
DocDBTrace Error: 0 : Operation will NOT be retried. Current attempt 0, Exception: Microsoft.Azure.Documents.NotFoundException: The value '' specified for query '$resolveFor' is invalid., documentdb-dotnet-sdk/1.19.1 Host/64-bit MicrosoftWindowsNT/6.2.9200.0
at Microsoft.Azure.Documents.DocumentServiceRequest..ctor(OperationType operationType, ResourceType resourceType, String path, Stream body, AuthorizationTokenType authorizationTokenType, NameValueCollection headers)
at Microsoft.Azure.Documents.DocumentServiceRequest.Create(OperationType operationType, String relativePath, Resource resource, ResourceType resourceType, AuthorizationTokenType authorizationTokenType, NameValueCollection headers, SerializationFormattingPolicy formattingPolicy, JsonSerializerSettings settings)
at Microsoft.Azure.Documents.Client.DocumentClient.<ReplaceDocumentCollectionPrivateAsync>d__123.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Documents.BackoffRetryUtility`1.<>c__DisplayClass2.<<ExecuteAsync>b__0>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.Documents.BackoffRetryUtility`1.<ExecuteRetry>d__1b.MoveNext()
Updated with code. I'm trying to share the creation/modify index code, so I call CreateDocumentCollectionIfNotExistAsync first and if the collection exists, then I modify the index policy to match the latest.
DocumentCollection appCollection = new DocumentCollection();
appCollection.Id = CosmosDbCollectionName;
// Set the index policy
var rrdc = await cdbClient.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri(CosmosDbDatabaseName), appCollection);
if (true == rrdc.StatusCode.IsSuccessCode())
{
// If OK was returned, the collection already existed.
if (HttpStatusCode.OK == rrdc.StatusCode)
{
var rr = await _cdbClient.ReplaceDocumentCollectionAsync(appCollection).ConfigureAwait(false);
if (false == rr.StatusCode.IsSuccessCode())
return false;
}
}

You need to pass the DocumentCollection resource instance returned from CreateDocumentCollectionIfNotExistsAsync to ReplaceDocumentCollectionAsync.
For example:
DocumentCollection appCollectionSpec = new DocumentCollection();
appCollection.Id = CosmosDbCollectionName;
// Set the index policy
ResourceResponse<DocumentCollection> rrdc = await cdbClient.CreateDocumentCollectionIfNotExistsAsync(UriFactory.CreateDatabaseUri(CosmosDbDatabaseName), appCollectionSpec);
if (true == rrdc.StatusCode.IsSuccessCode())
{
// If OK was returned, the collection already existed.
if (HttpStatusCode.OK == rrdc.StatusCode)
{
var rr = await _cdbClient.ReplaceDocumentCollectionAsync(rrdc.Resource).ConfigureAwait(false);
if (false == rr.StatusCode.IsSuccessCode())
return false;
}
}
I don't believe the DocumentCollection instance that is passed to CreateDocumentCollectionIfNotExists is modified by the call, as it is treated as a 'spec' object. The replace operation requires internal metadata that is only populated by resources returned from the server.

Related

HealthCheckResult how to return additional info in response?

Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult
public HealthCheckResult (Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus status, string description = null, Exception exception = null, System.Collections.Generic.IReadOnlyDictionary<string,object> data = null);
Parameters
status HealthStatus
A value indicating the status of the component that was checked.
description String
A human-readable description of the status of the component that was checked.
exception Exception
An Exception representing the exception that was thrown when checking for status (if any).
data IReadOnlyDictionary<String,Object>
Additional key-value pairs describing the health of the component.
Unfortunately trial-and-error shows that description is not returned in the health-check endpoint response.
catch(Exception ex)
{
return new HealthCheckResult(status: HealthStatus.Unhealthy,
description: ex.Message,
exception: ex);
}
I'd think that the exception message would be returned in the response and displayed in the browser but it's not.
Is there an undocumented mechanism to return additional info beyond Degraded Healthy Unhealthy etc. ?
The HealthCheckResult is a struct in .Net Core. In the implementation of method CheckHealthAsync of IHealthCheck interface, you can return the status along with custom description as below -
if (response.StatusCode == HttpStatusCode.OK)
{
return HealthCheckResult.Healthy("connected successfully.");
}
OR
return HealthCheckResult.Unhealthy("Failed to connect.)

Error when getAsync after adding column EF core

I init a User info table only not have FacebookID column, and there were 2 record. Now I add a FacebookID column to practice register by Facebook using migration EF core Framework. In first called, a record added and 2 FacebookID under is null. And I want to second called, It have to check that FacebookID is exist, If it is exist, please return message that FacebookID is exist. If it is not exist, add new User
I wrote a function to check that, because 2 Facebookid in image is null so It not working
RuleFor(model => model).MustAsync((x, cancellationToken) => FacebookIdMustUnique(x.FacebookId, cancellationToken))
.WithMessage(string.Format(Resource.Validation_Existed, Resource.FacebookId));
async Task<bool> FacebookIdMustUnique(string facebookId, CancellationToken cancellationToken = default(CancellationToken))
{
var user = await userService.GetAsync(x =>
x.FacebookId.Equals(facebookId, StringComparison.InvariantCultureIgnoreCase),
cancellationToken
);
return user == null;
}
image description here
I wrote a function to check that, because 2 Facebookid in image is null so It not working
Your following code will throw in this line when the Facebookid is null :
x.FacebookId.Equals(facebookId, StringComparison.InvariantCultureIgnoreCase)
To fix it, you need take consideration whether it is null before invoke its .Equals() method:
async Task FacebookIdMustUnique(string facebookId, CancellationToken cancellationToken = default(CancellationToken))
{
if(facebookId ==null){ return true; }
var user = await userService.GetAsync(
x => x.FacebookId.Equals(facebookId, StringComparison.InvariantCultureIgnoreCase),
cancellationToken
);
return user == null;
}
(In your case, it likely be fine if the facebook id is null, so I just return true)
As a reminder: it' always a good practice to check null for Nullable types.

InvalidOperationException: Role testRole does not exist

I was trying to let the accountController to assign roles to each newly registered user automatically, so I've ended up doing something like this:
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
//there is where the error is being raised.
await _userManager.AddToRoleAsync(user, "testRole");
if (result.Succeeded)
{
//here goes some code
//have also adding this line of code inside this if stmt
//await _userManager.AddToRoleAsync(user, "testRole");
}
AddErrors(result);
}
return View(model);
}
I did what other posts on StackOverFlow recommended but, I keep having this error:
InvalidOperationException: Role TESTROLE does not exist.
Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore+d__34.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task)
Microsoft.AspNetCore.Identity.UserManager+d__104.MoveNext()
System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task) System.Runtime.CompilerServices.TaskAwaiter.GetResult()
WebApplication2.Controllers.AccountController+d__17.MoveNext()
in AccountController.cs
Notes:
I was using PostgreSql on my project, so I've created a new project
with MSSQL and ended up with the same error.
I've made sure that the testRole is being in the table AspNetRoles. So ,there's no problem with that either!
so testRole is exact name which would then get normalized to TESTROLE how was TestRole created? I say this because Identity looks for the normalized version. Exception is pretty clear that it doesn't exist in this case. Basically if you didn't use RoleManager then something is wrong with the way you created the role
Another way to create the role would be using your database context and add in new roles that way but if you didn't use caps for the NormalizedName field entry then this is the error you will get

ReadAsMultipartAsync Throws System.ArgumentException

I have tried searching on here and Google for an answer to this but have yet to find one. I am using what I have found to be fairly standard for .NET 4.0 upload to Web API service. Here is the code:
public HttpResponseMessage Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
StringBuilder sb = new StringBuilder();
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MyMultipartFormDataStreamProvider(root);
var task = Request.Content.ReadAsMultipartAsync(provider).ContinueWith<HttpResponseMessage>(t =>
{
if (t.IsFaulted || t.IsCanceled)
{
Request.CreateErrorResponse(HttpStatusCode.InternalServerError, t.Exception);
}
// This will give me the form field data
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
sb.Append(string.Format("{0}: {1}", key, val));
}
}
// This will give me any file upload data
foreach (MultipartFileData file in provider.FileData)
{
sb.Append(file.Headers.ContentDisposition.FileName);
sb.Append("Server file path: " + file.LocalFileName);
}
return new HttpResponseMessage()
{
Content = new StringContent(sb.ToString())
};
});
return Request.CreateResponse(HttpStatusCode.OK);
}
When I create a very basic form with a input type=file and submit it I am getting an exception thrown for files over about 800Kb. Here is the exception:
System.ArgumentException was unhandled by user code
HResult=-2147024809
Message=Value does not fall within the expected range.
Source=mscorlib
StackTrace:
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode)
at System.Web.Hosting.IIS7WorkerRequest.GetServerVariableInternal(String name)
at System.Web.Hosting.IIS7WorkerRequest.GetServerVariable(String name)
at System.Web.Hosting.IIS7WorkerRequest.GetRemoteAddress()
at System.Web.HttpWorkerRequest.IsLocal()
at System.Web.Configuration.CustomErrorsSection.CustomErrorsEnabled(HttpRequest request)
at System.Web.HttpContextWrapper.get_IsCustomErrorEnabled()
at System.Web.Http.WebHost.HttpControllerHandler.<>c__DisplayClassa.<ConvertRequest>b__9()
at System.Lazy`1.CreateValue()
at System.Lazy`1.LazyInitValue()
at System.Lazy`1.get_Value()
at System.Web.Http.HttpConfiguration.ShouldIncludeErrorDetail(HttpRequestMessage request)
at System.Net.Http.HttpRequestMessageExtensions.CreateErrorResponse(HttpRequestMessage request, HttpStatusCode statusCode, Func`2 errorCreator)
at System.Net.Http.HttpRequestMessageExtensions.CreateErrorResponse(HttpRequestMessage request, HttpStatusCode statusCode, Exception exception)
at aocform.Controllers.ValuesController.<>c__DisplayClass2.<Post>b__1(Task`1 t) in c:\Users\fred_malone\Documents\Visual Studio 2012\Projects\aocform\aocform\Controllers\ValuesController.cs:line 30
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
InnerException:
I check the App_Data folder and I see part of the file there. This small part is not always the same size either, like maybe it cuts off at a certain size.
I have adjusted both the maxRequestLength and the maxAllowedContentLength to large numbers with no success.
What does this message mean and what should I be looking at to fix it?
Thanks.

app_offline.htm file being used to take webservice offline - possible to read contents of file?

I'm using an app_offline.htm file as described here : http://weblogs.asp.net/scottgu/archive/2005/10/06/426755.aspx to take an old asmx web service offline.
All works fine, and the client end gets a HTTP 503 exception like :
Exception : System.Net.WebException
The request failed with HTTP status 503: Service Unavailable.
Source : System.Web.Services
Stack trace :
at System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
My question : is it possible for the client application to read the contents of the app_offline.htm file which would have been returned ? The basic HTML in that file has helpful text like : "The application is currently undergoing maintenance". I can see the contents of this file being returned in the response using Fiddler.
It would be useful to be able to parse this html response to provide more info to the user. (i.e. so it is possible to distinguish between a 503 error due to system maintenance, and other 503s due to system being overloaded etc).
EDIT : BluesRockAddict's response sounded good, but the stream seems to be unavailable at this time. e.g. :
// wex is the caught System.Net.WebException
System.Net.WebResponse resp = wex.Response;
byte[] buff = new byte[512];
Stream st = resp.GetResponseStream();
int count = st.Read(buff, 0, 512);
The last line above which attempts to read the stream gives :
Exception : System.ObjectDisposedException
Cannot access a closed Stream.
Source : mscorlib
Stack trace :
at System.IO.__Error.StreamIsClosed()
at System.IO.MemoryStream.Read(Byte[] buffer, Int32 offset, Int32 count)
credit goes to BluesRockAddict, adding to his answer, this is how you can read the content of html page.
catch (WebException ex)
{
if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.ServiceUnavailable)
{
using (Stream stream = ex.Response.GetResponseStream())
{
using(StreamReader reader = new StreamReader(stream))
{
var message = reader.ReadToEnd();
}
}
}
}
You should use WebException.Response to retrieve the message:
using (WebClient wc = new WebClient())
{
try
{
string content = wc.DownloadString(url);
}
catch (WebException ex)
{
if (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.ServiceUnavailable)
{
message = ex.Response
}
}
}

Resources