To get the inline count in odata style from a webapi2 controller I read on this page:
http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/supporting-odata-query-options that I should return a PagedResult from my method. I made my method in my apicontroller like this:
public PageResult<Software> Get(ODataQueryOptions<Software> options)
{
ODataQuerySettings settings = new ODataQuerySettings()
{
};
IQueryable results = options.ApplyTo(db.Software, settings);
return new PageResult<Software>(
results as IEnumerable<Software>,
Request.ODataProperties().NextLink,
Request.ODataProperties().TotalCount
);
}
This works fine for request like this:
http://dummy.com/api/Softwareapi?$inlinecount=allpages&$filter=Deleted%20eq%20false&$orderby=SequenceNo&$top=7&$skip=0
But for a request like this:
http://dummy.com/api/Softwareapi?$inlinecount=allpages&$filter=Deleted%20eq%20false&$orderby=SequenceNo&$top=7&$skip=0&$expand=Supplier
I get:
<Error>
<Message>An error has occurred.</Message>
<ExceptionMessage>Value cannot be null. Parameter name: data</ExceptionMessage>
<ExceptionType>System.ArgumentNullException</ExceptionType>
<StackTrace>
at System.Web.Http.OData.PageResult`1..ctor(IEnumerable`1 items, Uri nextPageLink, Nullable`1 count) at DigiCampuz.Controllers.SoftwareApiController.Get(ODataQueryOptions`1 options) in c:\Users\bzs\Documents\Visual Studio 2012\Projects\DigiCampuz Webapp\DigiCampuz\Controllers\SoftwareApiController.cs:line 41 at lambda_method(Closure , Object , Object[] ) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments) at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken) --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
If I use quick-watch feature in the vs debugger I can see results has the correct amount of items and those items have suppliers, but I cannot seem to get pagedresult to see that.
Does anybody here want to help me with this?
Related
I want to create mockable handler for HttpClient, so I define it like this:
type TestHandler() =
inherit HttpMessageHandler()
abstract SendAsync: HttpRequestMessage * CancellationToken -> Task<HttpResponseMessage>
override this.SendAsync(request, cancellationToken) = base.SendAsync(request, cancellationToken)
but I get the error:
Error FS0361
The override SendAsync : HttpRequestMessage * CancellationToken -> Task<HttpResponseMessage>
implements more than one abstract slot,
e.g. abstract member TestHandler.SendAsync : HttpRequestMessage * CancellationToken -> Task<HttpResponseMessage>
and
HttpMessageHandler.SendAsync(request: HttpRequestMessage, cancellationToken: CancellationToken) : Task<HttpResponseMessage>
My intent is to create public overridable method which can be mocked with Foq, and which is simply called in base SendAsync.
If I name abstract method differently, e.g. MockableSendAsync compiler does not complain, but is it possible to reuse the name? (Is it possible to make method sealed?)
If I understand the problem correctly, the issue is that the virtual SendAsync method in HttpMessageHandler is protected, but want to create a type where it is public so that it can be mocked easily.
I don't think there is a way to hide virtual method with another new (public) virutal method in F#, but I think your use case would work if you defined a virutal method of some other name and called it from the original SendAsync method:
type TestHandler() =
inherit HttpMessageHandler()
abstract MockableSendAsync:
HttpRequestMessage * CancellationToken -> Task<HttpResponseMessage>
default this.MockableSendAsync(request, cancellationToken) =
base.SendAsync(request, cancellationToken)
override this.SendAsync(request, cancellationToken) =
this.MockableSendAsync(request, cancellationToken)
I have developed asp.net core 3.1 based web api and implemented the HealthCheck and HealthCheckUI based on the documentation available at : https://github.com/Xabaril/AspNetCore.Diagnostics.HealthChecks
Before implementing it in the original project I have developed a POC and it worked fine as expected.
Now I tried to do the same in the original project which is leveraging Azure Kubernetes services and deployed in Azure Dev Spaces.
Here goes my code :
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddCustomHealthChecks(Configuration);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseEndpoints(builder =>
{
builder.MapHealthChecks("/health", new HealthCheckOptions()
{AllowCachingResponses = false}).RequireCors(CorsPolicyName.AllowAny);
builder.MapHealthChecks("/healthcheck", new HealthCheckOptions()
{Predicate = _ => true, ResponseWriter = UIResponseWriter.WriteHealthCheckUIResponse}).RequireCors(CorsPolicyName.AllowAny);
}
app.UseHealthChecksUI();
}
public static IServiceCollection AddCustomHealthChecks(this IServiceCollection services, IConfiguration configuration)
{
var cosmosDBServiceEndPoint = configuration.GetValue<string>("CosmosDBEndpoint");
var cosmosDBAuthKeyOrResourceToken = configuration.GetValue<string>("CosmosDBAccessKey");
var cosmosDBConnectionString = $"AccountEndpoint={cosmosDBServiceEndPoint};AccountKey={cosmosDBAuthKeyOrResourceToken};";
var hcBuilder = services.AddHealthChecks();
hcBuilder.AddCheck("self", () => HealthCheckResult.Healthy()).AddCosmosDb(connectionString: cosmosDBConnectionString, name: "CosmosDB-check", failureStatus: HealthStatus.Degraded, tags: new string[]{"cosmosdb"});
services.AddHealthChecksUI();
return services;
}
On deploying the above code in Azure Dev Space I am getting the below error:
An exception occurred while iterating over the results of a query for context type 'HealthChecks.UI.Core.Data.HealthChecksDb'.
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'near "(": syntax error'.
at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext()
at Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext()
at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
at Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor.AsyncQueryingEnumerable`1.AsyncEnumerator.MoveNextAsync()
Can anyone help me to know how to fix this issue?
I have three Repository classes, which are:
1. ITechniqueRepository
2. ITechniqueItemRepository
3. ITechniqueAssesstmentRepository
There is another Service class, which is:
ITechniqueService
In ITechniqueService constructor, I have the following code to resolve Dependency Injection.
private readonly ITechniqueRepository _techniqueRepository;
private readonly ITechniqueItemRepository _techniqueItemRepository;
private readonly ITechniqueAssesstmentRepository _techniqueAssesstmentRepository;
public TechniqueService(
ITechniqueRepository techniqueRepository,
ITechniqueItemRepository techniqueItemRepository,
ITechniqueAssesstmentRepository techniqueAssesstmentRepository
) : base(unitOfWork, settings, logger)
{
_techniqueRepository = techniqueRepository;
_techniqueItemRepository = techniqueItemRepository;
_techniqueAssesstmentRepository = techniqueAssesstmentRepository;
}
In my controller constructor, I have the following code to resolve the dependency.
private readonly ITechniqueService _techniqueService;
public TechniqueController(
ITechniqueService techniqueService
)
{
_techniqueService = techniqueService;
}
And in my Startup class, I have the bellow code:
services.AddScoped<ITechniqueRepository, TechniqueRepository>();
services.AddScoped<ITechniqueItemRepository, TechniqueItemRepository>();
services.AddScoped<ITechniqueAssessmentRepository, TechniqueAssessmentRepository>();
services.AddScoped<ITechniqueService, TechniqueService>();
The problem is when I execute my service, I get the below exception as response result.
{
"StatusCode": 3,
"Message": "Unable to resolve service for type 'Data.Repositories.ITechniqueAssesstmentRepository' while attempting to activate
'Services.TechniqueService'.",
"MessageDetail": "at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateArgumentCallSites(Type
serviceType, Type implementationType, ISet1 callSiteChain,
ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)\r\n at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(Type
serviceType, Type implementationType, ISet1 callSiteChain)\r\n at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(ServiceDescriptor
descriptor, Type serviceType, ISet1 callSiteChain)\r\n at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateExact(Type
serviceType, ISet1 callSiteChain)\r\n at
Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type
serviceType, ISet1 callSiteChain)\r\n at
Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type
serviceType, ServiceProvider serviceProvider)\r\n at
System.Collections.Concurrent.ConcurrentDictionaryExtensions.GetOrAdd[TKey,TValue,TArg](ConcurrentDictionary2
dictionary, TKey key, Func`3 valueFactory, TArg arg)\r\n at
Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type
serviceType)\r\n at
Microsoft.Extensions.Internal.ActivatorUtilities.GetService(IServiceProvider
sp, Type type, Type requiredBy, Boolean
isDefaultParameterRequired)\r\n at lambda_method(Closure ,
IServiceProvider , Object[] )\r\n at
Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.g__CreateController|0(ControllerContext
controllerContext)\r\n at
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State&
next, Scope& scope, Object& state, Boolean& isCompleted)\r\n at
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext()\r\n---
End of stack trace from previous location where exception was thrown
---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n
at
System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task
task)\r\n at
Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__23.MoveNext()",
"Errors": {} }
Where did I make a mistake?
With the following query i get a Neo4jclient internal ArgumentException when the result is empty:
graphClient.Cypher
.Match("(a:Application {Id: {pId}})")
.WithParams(new { pId = request.Id })
.With("a")
.OptionalMatch("(a)-[:Uses]->(db:Database)")
.ReturnDistinct(db => db.As<DatabaseDto>());
The result is:
Additional information: Neo4j returned a valid response, however Neo4jClient was unable to deserialize into the object structure you supplied.
Include this raw JSON, with any sensitive values replaced with non-sensitive equivalents:
{
"columns" : [ "db" ],
"data" : [ [ null ] ]
}
Parameter name: content
Source=Neo4jClient
ParamName=content
StackTrace:
at Neo4jClient.Serialization.CypherJsonDeserializer`1.Deserialize(String content) in c:\TeamCity\buildAgent\work\5bae2aa9bce99f44\Neo4jClient\Serialization\CypherJsonDeserializer.cs:line 61
at Neo4jClient.GraphClient.<>c__DisplayClass1e`1.<Neo4jClient.IRawGraphClient.ExecuteGetCypherResultsAsync>b__1d(Task`1 responseTask) in c:\TeamCity\buildAgent\work\5bae2aa9bce99f44\Neo4jClient\GraphClient.cs:line 820
at System.Threading.Tasks.ContinuationResultTaskFromResultTask`2.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=While trying to map some JSON into an object of type ....DatabaseDto, we failed to find an expected property (Id) in the JSON at path data[0][0].
The JSON block for this token was:
Source=Neo4jClient
StackTrace:
at Neo4jClient.Serialization.CommonDeserializerMethods.Map(DeserializationContext context, Object targetObject, JToken parentJsonToken, IEnumerable`1 typeMappings, Int32 nestingLevel) in c:\TeamCity\buildAgent\work\5bae2aa9bce99f44\Neo4jClient\Serialization\CommonDeserializerMethods.cs:line 321
at Neo4jClient.Serialization.CommonDeserializerMethods.CreateAndMap(DeserializationContext context, Type type, JToken element, IEnumerable`1 typeMappings, Int32 nestingLevel) in c:\TeamCity\buildAgent\work\5bae2aa9bce99f44\Neo4jClient\Serialization\CommonDeserializerMethods.cs:line 274
at Neo4jClient.Serialization.CypherJsonDeserializer`1.<>c__DisplayClass1b.<ParseInSingleColumnMode>b__19(JToken row) in c:\TeamCity\buildAgent\work\5bae2aa9bce99f44\Neo4jClient\Serialization\CypherJsonDeserializer.cs:line 175
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at Neo4jClient.Serialization.CypherJsonDeserializer`1.Deserialize(String content) in c:\TeamCity\buildAgent\work\5bae2aa9bce99f44\Neo4jClient\Serialization\CypherJsonDeserializer.cs:line 34
InnerException: System.InvalidOperationException
HResult=-2146233079
Message=Cannot access child value on Newtonsoft.Json.Linq.JValue.
Source=Newtonsoft.Json
StackTrace:
at Newtonsoft.Json.Linq.JToken.get_Item(Object key)
at Neo4jClient.Serialization.CommonDeserializerMethods.Map(DeserializationContext context, Object targetObject, JToken parentJsonToken, IEnumerable`1 typeMappings, Int32 nestingLevel) in c:\TeamCity\buildAgent\work\5bae2aa9bce99f44\Neo4jClient\Serialization\CommonDeserializerMethods.cs:line 317
InnerException:
I couldn't recreate the exact exception you had here, but I've recreated the scenario and discovered a bug. That's fixed in 1.0.0.654.
https://github.com/Readify/Neo4jClient/commit/25b8d3701a0745fbb577e81005da8254c0d67f6f
Try upgrading. If it works, please mark this answer as accepted. If it doesn't, please do what the exception says and raise the issue at https://github.com/Readify/Neo4jClient/issues?state=open instead of here on StackOverflow.
I am trying to use NHibernate to save to a database in the same transaction as sending a message on the bus from inside an MVC application:
public void DoSomethingToEntity(Guid id)
{
var session = _sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
using (var transactionScope = new TransactionScope())
{
var myEntity = _session.Get(id);
myEntity.DoSomething();
_session.Save(myEntity);
_bus.Send(myMessage);
transactionScope.Complete();
}
session.Dispose();
}
In the configuration, .MsmqTransport() is set with .IsTransactional(true).
If I do this inside a message handler (which is wrapped in its own transaction so does not need the TransactionScope) Then it all works as expected, and if I include an exception, both fail.
However, if I do it inside my own transaction in an MVC application, I get the following error after transactionScope.Complete() when leaving the using block.:
'The operation is not valid for the current state of the enlistment.'
Stack Trace:
at System.Transactions.EnlistmentState.InternalIndoubt(InternalEnlistment enlistment)
at System.Transactions.VolatileDemultiplexer.BroadcastInDoubt(VolatileEnlistmentSet& volatiles)
at System.Transactions.TransactionStatePromotedIndoubt.EnterState(InternalTransaction tx)
at System.Transactions.TransactionStatePromotedBase.InDoubtFromEnlistment(InternalTransaction tx)
at System.Transactions.DurableEnlistmentDelegated.InDoubt(InternalEnlistment enlistment, Exception e)
at System.Transactions.SinglePhaseEnlistment.InDoubt(Exception e)
at System.Data.SqlClient.SqlDelegatedTransaction.SinglePhaseCommit(SinglePhaseEnlistment enlistment)
at System.Transactions.TransactionStateDelegatedCommitting.EnterState(InternalTransaction tx)
at System.Transactions.TransactionStateDelegated.BeginCommit(InternalTransaction tx, Boolean asyncCommit, AsyncCallback asyncCallback, Object asyncState)
at System.Transactions.CommittableTransaction.Commit()
at System.Transactions.TransactionScope.InternalDispose()
at System.Transactions.TransactionScope.Dispose()
at HumanResources.Application.Implementations.HolidayService.Book(BookHolidayRequest request) in C:\Users\paul.davies\Documents\GitHub\EdaCalendarExample\HumanResources.Application\Implementations\HolidayService.cs:line 76
at HumanResources.UI.Controllers.HolidayController.BookUpdate(BookHolidayViewModel viewModel) in C:\Users\paul.davies\Documents\GitHub\EdaCalendarExample\HumanResources.UI\Controllers\HolidayController.cs:line 82
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c_DisplayClass15.b_12()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
Latest Edit:
This code works:
public void DoSomethingToEntity(Guid id)
{
var session = _sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
using (var transactionScope = new TransactionScope())
{
var myEntity = _session.Get(id);
_bus.Send(myMessage);
transactionScope.Complete();
}
session.Dispose();
}
This code creates the error:
public void DoSomethingToEntity(Guid id)
{
var session = _sessionFactory.OpenSession();
CurrentSessionContext.Bind(session);
using (var transactionScope = new TransactionScope())
{
var myEntity = _session.Get(id);
myEntity.AnyField = "a new value";
_bus.Send(myMessage);
transactionScope.Complete();
}
session.Dispose();
}
Note that I am not saving th entity in either example. The difference is in the second example, I am modifying the entity I have got from NHibernate. This is 100% reproducable.
This may not be related but you still have to call _session.Flush() before committing a TransactionScope even if the session flush mode is set to Commit - that only works for NH provided transactions.
As far as I can tell there is no way of being notified when a new System.Transactions.Transaction is created, and looking at the code in NHibernate it doesn't seem to have any code to deal with the situation where the TransactionScope is created AFTER creating the session.
When you create the session, it will try to enlist in the current Transaction, and if there isn't one then the session won't enlist in the transaction. I suspect that this is what's causing the transaction to fail on commit.
I would suggest creating the session INSIDE the TransactionScope - also check whether you are calling session.BeginTransaction somewhere before the TransactionScope.