On a standard DocumentStore we can specify the default database to use as:
documentStore = new DocumentStore {
DefaultDatabase = "Comics"
}
How do we go about doing the same for a ShardedDocumentStore?
I see the answer is quite obvious now.
The DefaultDatabase can be set on each of the individual shards that are set up before the SharededDocumentStore is created.
var shards = new Dictionary<string, IDocumentStore>
{
{ "Marvel", new DocumentStore {
Url = "http://localhost:8080",
DefaultDatabase = "Comics" }
},
{ "DC Comics", new DocumentStore {
Url = "http://localhost:8081",
DefaultDatabase = "Comics" }
}
};
Related
I am writing unit test for Authorization filter to validate the request/ token. However, it return null. not sure what is wrong.
https://programmium.wordpress.com/2020/04/30/unit-testing-custom-authorization-filter-in-net-core/
public class UserAuthorizationTests
{
private readonly Mock<ILogger<UserAuthorizationFilter>> _mocklogger;
private readonly Mock<IOptions<UserAuthorisationOptions>> _mockOption;
public UserAuthorizationTests()
{
_mocklogger = new Mock<ILogger<UserAuthorizationFilter>>();
_mockOption = new Mock<IOptions<UserAuthorisationOptions>>();
}
[Fact]
public void UserAuthorizationTest()
{
var httpContextMock = new Mock<HttpContext>();
httpContextMock.Setup(a => a.Request.Headers["UserAuthorization"]).Returns("test");
ActionContext fakeActionContext =
new ActionContext(httpContextMock.Object,
new Microsoft.AspNetCore.Routing.RouteData(),
new Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor());
AuthorizationFilterContext fakeAuthFilterContext =
new AuthorizationFilterContext(fakeActionContext,
new List<IFilterMetadata>());
UserAuthorizationFilter userAuthorizationFilter =
new UserAuthorizationFilter(_mockOption.Object, _mocklogger.Object);
userAuthorizationFilter.OnAuthorization(fakeAuthFilterContext);
Assert.NotEqual(typeof(UnauthorizedResult), userAuthorizationFilter.GetType());
}
}
you said “it return null”,it may help if you could describe it more clearly
I wrote the xunit test using Moq as below:
var httpContextMock = new Mock<HttpContext>();
httpContextMock.Setup(a => a.Request.Headers["Authorization"]).Returns("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiSmVmZmNreSIsIm5iZiI6MTY1MjA4NTg1NSwiZXhwIjoxNjUyMDg2MTU1LCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjUwMDAiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjUwMDEifQ.cOpCN93U108Xr_km7GunxAJMrqx3LPnYAl3gLnXDW5M");
ActionContext fakeActionContext =new ActionContext(httpContextMock.Object, new Microsoft.AspNetCore.Routing.RouteData(),
new Microsoft.AspNetCore.Mvc.Abstractions.ActionDescriptor());
JwksFilter jwksfilter = new JwksFilter();
AuthorizationFilterContext fakeAuthFilterContext =new AuthorizationFilterContext(fakeActionContext, new List<IFilterMetadata>() { });
jwksfilter.OnAuthorization(fakeAuthFilterContext);
Assert.Equal(typeof(UnauthorizedResult), fakeAuthFilterContext.Result.GetType());
Codes in my filter:
public void OnAuthorization(AuthorizationFilterContext context)
{
var jwks = context.HttpContext.Request.Headers["Authorization"].ToString();
var validateParameters = new TokenValidationParameters()
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("1234567890123456")),
ValidateIssuer = true,
ValidIssuer = "http://localhost:5000",
ValidateAudience = true,
ValidAudience = "http://localhost:5001",
ValidateLifetime = true,
ClockSkew = TimeSpan.FromMinutes(5)
};
var valiresult = ValidateToken(jwks, validateParameters);
if (valiresult == false)
{
context.Result = new UnauthorizedResult();
}
}
private static bool ValidateToken(string token, TokenValidationParameters validationParameters)
{
var tokenHandler = new JwtSecurityTokenHandler();
try
{
tokenHandler.ValidateToken(token, validationParameters, out var validatedToken);
return true;
}
catch (Exception e)
{
return false;
}
}
And the result:
Is it possible to send graphQL queries with the standard httpclient in .NET core?
When I try to send my query with a client.post I get "Expected { or [ as first syntax token."
How can I send GraphQL queries with a httpclient.
Without having to use a library (like GraphQLHttpClient etc..)
Got it:
Just add "query" as a json object. Like this:
{"query" : "query { __schema { queryType { name } mutationType { name } types { name } directives { name } } }"}
In .NET you can use this in an HTTP post (don't forget to string escape the double quotes
private static string myquery = "{ \"query\" : \"query { __schema { queryType { name } mutationType { name } types { name } directives { name } } }\" }";
Here's an example of how to call a GraphQL endpoint with HttpClient in .net Core:
public async Task<string> GetProductsData(string userId, string authToken)
{
var httpClient = new HttpClient
{
BaseAddress = new Uri(_apiUrl)
};
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authToken);
var queryObject = new
{
query = #"query Products {
products {
id
description
title
}
}",
variables = new { where = new { userId = userId } }//you can add your where cluase here.
};
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
Content = new StringContent(JsonConvert.SerializeObject(queryObject), Encoding.UTF8, "application/json")
};
using (var response = await httpClient.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var responseString = await response.Content.ReadAsStringAsync();
return responseString;
}
}
I'm trying to:
[EnableQuery]
[HttpGet]
[ODataRoute("")]
public IHttpActionResult Get(ODataQueryOptions<UserODataModel> options)
{
var users = _repository.RetrieveOData();
var serialQuery = JsonConvert.SerializeObject(options, jsonOptions);
//save serialQuery somewhere
return Ok(users);
}
But got
Newtonsoft.Json.JsonSerializationException: 'Error getting value from 'ReadTimeout' on 'Microsoft.Owin.Host.SystemWeb.CallStreams.InputStream'.'
"Timeouts are not supported on this stream."
I know there is already a question about serialize Stream:
Newtonsoft Json.net - how to serialize content of a stream?
But in this case i can't "extract stream value" from ODataQueryOptions, or can I?
Some ideia?
Since we work on the same company, if anyone is interested, we found a way, maybe not the pretty way, to serialize an ODataQueryOptions:
public static ODataQueryOptions DeserializeQueryOptions(SerializedQueryOptions options)
{
var uri = new Uri(teste.OriginalUri);
var model = ODataConfig.Model; //GetEdmModel
var segment = model.EntityContainer.FindEntitySet(options.EdmType);
var newPath = new Microsoft.AspNet.OData.Routing.ODataPath(new EntitySetSegment(segment));
var httpConfiguration = new HttpConfiguration();
httpConfiguration.EnableDependencyInjection();
var request = new HttpRequestMessage(HttpMethod.Get, uri)
{
Properties =
{
{ HttpPropertyKeys.HttpConfigurationKey, httpConfiguration },
}
};
var context = new ODataQueryContext(model, options.EntityType, newPath);
var oDataQueryOptions = new ODataQueryOptions(context, request);
return oDataQueryOptions;
}
public static SerializedQueryOptions SerializeQueryOptions(ODataQueryOptions options)
{
return new SerializedQueryOptions
{
OriginalUri = options.Request.RequestUri.AbsoluteUri,
EdmType = options.Context.NavigationSource.Name,
EntityType = options.Context.ElementClrType
};
}
After you serialize it to an object you can serialize it to a JSON string:
var queryOptionsSerialized = new SerializedQueryOptions()
{
OriginalUri = "http://localhost:25723/odata/users?$skip=0&$top=2&$orderby=fullName&$count=true",
EdmType = "users",
EntityType = typeof(UserODataModel)
};
var json = JsonConvert.SerializeObject(queryOptionsSerialized);
var deserialized = JsonConvert.DeserializeObject<SerializedQueryOptions>(json);
var options = ODataQueryOptionsHelper.DeserializeQueryOptions(deserialized);
In case One is not using OData routing or using an ApiController (not ODataController),
modify the way of Obtaining ODataPath to:
ODataUriParser parser = new ODataUriParser(model, serviceRoot, requestUri);
ODataPath path = parser.ParsePath();
//var newPath = new Microsoft.AspNet.OData.Routing.ODataPath(new EntitySetSegment(segment));
Microsoft.AspNet.OData.Routing.ODataPath newPath = new Microsoft.AspNet.OData.Routing.ODataPath(path.FirstOrDefault());
where the serviceRoot is the Url part other that the path defined in the model.
I have some Ranged Facets defined in a FacetSetup document. I like having the ability to retrieve individual Facets from a FacetSetup (by specifying them instead of the Id of the FacetSetup in my call to ToFacets()), so I tried to do that with these Ranged Facets but have been unsuccessful so far.
Here is my failing test. Any tips?
using Raven.Abstractions.Data;
using Raven.Abstractions.Indexing;
using Raven.Client;
using Raven.Client.Embedded;
using Raven.Tests.Helpers;
using System.Collections.Generic;
using System.Linq;
using Xunit;
namespace RavenDBTests
{
public class RangedFacetTests : RavenTestBase
{
[Fact]
public void RangedFacetTest()
{
using (EmbeddableDocumentStore documentStore = NewDocumentStore())
{
// create and store an index
Dictionary<string, string> analyzers = new Dictionary<string, string>();
analyzers.Add("MyProperty", "");
Dictionary<string, SortOptions> sortOptions = new Dictionary<string, SortOptions>();
sortOptions.Add("MyProperty", SortOptions.Long);
IndexDefinition indexDefinition = new IndexDefinition()
{
Analyzers = analyzers,
SortOptions = sortOptions,
Map = #"from d in docs
select new
{
MyProperty = d.MyProperty
}",
};
documentStore.DatabaseCommands.PutIndex("MyIndex", indexDefinition);
using (IDocumentSession documentSession = documentStore.OpenSession())
{
// store some sample documents
documentSession.Store(new { MyProperty = 10 });
documentSession.Store(new { MyProperty = 25 });
documentSession.Store(new { MyProperty = 100 });
// store a facetsetup with one ranged facet
documentSession.Store(new FacetSetup
{
Id = "facets/MyFacetSetup",
Facets = new List<Facet>()
{
new Facet()
{
Mode = FacetMode.Ranges,
Name = "MyProperty_Range",
Ranges = new List<string>()
{
"[0x0000000000000001 TO 0x0000000000000032]"
}
}
}
}, "facets/MyFacetSetup");
documentSession.SaveChanges();
}
// let that process
WaitForIndexing(documentStore);
using (IDocumentSession documentSession = documentStore.OpenSession())
{
// retrieve ALL facets
FacetResults facetResults1 = documentSession.Query<dynamic>("MyIndex").ToFacets("facets/MyFacetSetup");
Xunit.Assert.True(facetResults1.Results.Values.First().Values.First().Hits > 0);
// retrieve SPECIFIED facets
FacetResults facetResults2 = documentSession.Query<dynamic>("MyIndex").ToFacets(new List<Facet>()
{
new Facet()
{
Mode = FacetMode.Ranges,
Name = "MyProperty_Range"
}
},
0,
null);
// this fails: why can't I specify the ranged facet?
Xunit.Assert.True(facetResults2.Results.Values.First().Values.First().Hits > 0);
}
}
}
}
}
You don't specify what the actual ranges are in the code.
In RavenDB, you have two ways to create facets. One is to specify the facet doc id, and the second is to actually pass the facets.
In this case, you are passing a range facets without any ranges, so it returns no results.
Use this code:
FacetResults facetResults2 = documentSession.Query<dynamic>("MyIndex").ToFacets(new List<Facet>()
{
new Facet()
{
Mode = FacetMode.Ranges,
Name = "MyProperty_Range",
Ranges = new List<string>()
{
"[0x0000000000000001 TO 0x0000000000000032]"
}
}
},
0,
null);
I'm creating objects and posting them to a webapi. Basically I just can't get the darn things to serialize so as to include the $type info in the json. The following is the code I'm attempting to write. Afterwards is the json I would expect.
var cds = new List<CreditDefaultSwaps>()
{
new CreditDefaultSwaps() { ModelNumber = "SP8A1ETA", BrokerSpread = 0},
new CreditDefaultSwaps() { ModelNumber = "SP3A0TU1", BrokerSpread = 0},
new CreditDefaultSwaps() { ModelNumber = "SP4A102V", BrokerSpread = 0}
};
var client = new HttpClient {BaseAddress = new Uri("http://localhost/BloombergWebAPI/api/")};
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// set up request object
var oContract = new WebApiDataServiceRequest
{
RequestType = ReferenceDataRequestServiceTypes.ReferenceDataRequest,
SwapType = BloombergWebAPIMarshal.SwapType.CDS,
SecurityList = cds
};
Tried something like this and the var content was formatted as I would expect
however I couldn't post the data using postasjsonasync
//var content = JsonConvert.SerializeObject(oContract, Formatting.Indented,
// new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Objects });
Console.ReadLine();
var response = client.PostAsJsonAsync("bloombergapi/processbloombergrequest", oContract).Result;
The following is the json I'm trying to post. What am I missing in the above code, I'm sure it's something silly.
{
"$type": "BloombergWebAPIMarshal.WebApiDataServiceRequest, BloombergWebAPIMarshal",
"RequestType": 3,
"SwapType": 1,
"SecurityList": [
{
"$type": "BloombergWebAPIMarshal.CreditDefaultSwaps, BloombergWebAPIMarshal",
"ModelNumber": "SP8A1ETA",
"BrokerSpread": 0
},
{
"$type": "BloombergWebAPIMarshal.CreditDefaultSwaps, BloombergWebAPIMarshal",
"ModelNumber": "SP3A0TU1",
"BrokerSpread": 0
},
{
"$type": "BloombergWebAPIMarshal.CreditDefaultSwaps, BloombergWebAPIMarshal",
"ModelNumber": "SP4A102V",
"BrokerSpread": 0
}
]
}
Created another overload Used this call to produce proper request:
var response = client.PostAsJsonAsync("processbloombergrequest", oContract, TypeNameHandling.Objects).Result
This is the new overload
public static Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, string requestUri, T value, TypeNameHandling typeNameHandling)
{
return client.PostAsJsonAsync<T>(requestUri, value, CancellationToken.None, typeNameHandling);
}
public static Task<HttpResponseMessage> PostAsJsonAsync<T>(this HttpClient client, string requestUri, T value, CancellationToken cancellationToken, TypeNameHandling typeNameHandling)
{
var formatter = new JsonMediaTypeFormatter
{
SerializerSettings = new JsonSerializerSettings()
{
TypeNameHandling = typeNameHandling
}
};
return client.PostAsync<T>(requestUri, value, formatter, cancellationToken);
}