How to test a IAppSettings in ServiceStack? - servicestack

In ServiceStack there is an IAppSettings as follows:
var appSettings = new AppSettings();
DateTime lastUpdate = appSettings.Get<DateTime>("LastUpdated");
IList<string> allowedUsers = appSettings.GetList("AllowedUsers");
var redisConf = appSettings.Get<RedisConfig>("RedisConf");
How can I create an instance of AppSettings with properties in code?
I want to create a IAppSettings in code for testing and not to take the values from a configuration file, e.g., web.config.

You could also use a mocking framework like moq to stub out the implementation of the IAppSettings interface:
var appSettings = new Mock<IAppSettings>();
appSettings.Setup(s => s.Get<DateTime>("LastUpdated")).Returns(new DateTime(2015, 2, 1));
Then, in your test, just pass appSettings.Object to any service/component that needs an IAppSettings.

The different IAppSettings providers are listed AppSettings Docs, e.g. the DictionarySettings lets you populate the settings from a .NET Dictionary<string,string>.
The AppSettingsTests will also be helpful to see how to test different AppSettings providers.

Related

Pulumi: Missing PrimaryAccessKey for EventGrid Topic

I'm using Pulumi 1.16 with dotnet/C# and the AzureNative stack. I try to create an EventGridTopic. To access the created resource's properties later I pull some output values.
Example code:
var topic = new Topic("eventgrid-topic-status", new TopicArgs
{
TopicName = "egt-status-dev",
ResourceGroupName = "rg-testapp-dev",
Location = "westeurope"
});
var endPointOutput = topic.Endpoint;
var endPointAccessKey = ""; // missing output property
The resource is being created. I found no way to get the access key properties:
PrimaryAccessKey
SecondaryAccessKey
In the former (elder) Azure stack the properties exist. But in Azure Native stack not. Is that on purpose, just work in progress, has been forgotten or is there some other way to retrieve these properties on this object?
This is output on Azure (old stack):
This is Azure Native, clearly the keys are missing:
I doubt that this happens accidentally and would like to understand what to do.
Azure API (and therefore Azure Native resources) return no sensitive information in their outputs automatically to minimize security risks. You have to make an explicit call to retrieve those.
In this case, you likely need to invoke the function listTopicSharedAccessKeys.
You will want to call the function from within an Apply to make sure that it's triggered only after the topic is created (e.g., not during preview):
var keys = topic.Name.Apply(topicName => ListTopicSharedAccessKeys.InvokeAsync(
new ListTopicSharedAccessKeysArgs
{
ResourceGroupName = "rg-testapp-dev",
TopicName = topicName
}));
If you don't want to hardcode the resource group name:
let keys = pulumi.all([rg.name, topic.name]).apply(arr =>
azn.eventgrid.listTopicSharedAccessKeys(
{
resourceGroupName: arr[0],
topicName: arr[1]
}
)
);
keys.apply(x => pulumi.log.info(x.key1 ?? ""));

How to access all ASP.NET Identity 2.0 PasswordValidator properties?

I set multiple properties on the PasswordValidator, but the only rule that is checked is password length.
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator()
{
RequiredLength = int.Parse(ConfigurationManager.AppSettings["PasswordRequiredLength"]),
RequireNonLetterOrDigit = bool.Parse(ConfigurationManager.AppSettings["PasswordRequireNonLetterOrDigit"]),
RequireDigit = bool.Parse(ConfigurationManager.AppSettings["PasswordRequireDigit"]),
RequireLowercase = bool.Parse(ConfigurationManager.AppSettings["PasswordRequireLowercase"]),
RequireUppercase = bool.Parse(ConfigurationManager.AppSettings["PasswordRequireUppercase"])
};
This is pretty much copied from the ASP.NET Identity sample app except the values are from config instead of hard-coded.
When I view the definition of PasswordValidator() I see that these properties are all defined (and it compiles and runs of course). However, I notice when I test changing a password that only the length causes validation error. The AccountController had this code from the sample:
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
To get a better look I added
IdentityResult resultPassword = await UserManager.PasswordValidator.ValidateAsync(model.NewPassword);
if (resultPassword.Succeeded)
{
IdentityResult result = await UserManager.ChangePasswordAsync(User.Identity.GetUserId(), model.OldPassword, model.NewPassword);
and I notice that userManager.PasswordValidator is of class MinimumLengthValidator, not the PasswordValidator I thought we started with. Of course, this explains the behavior, but I am at a loss to determine how to
Correctly add the "full" PassordValidator to my userManager and/or
Access the properties of the PassordValidator (such as RequireDigit, RequireUppercase, etc.)
Note, I have attempted
PasswordValidator myPV = (PasswordValidator)UserManager.PasswordValidator;
which results in a Unable to cast object of type 'Microsoft.AspNet.Identity.MinimumLengthValidator' to type 'Microsoft.AspNet.Identity.PasswordValidator' error.
Best,
Scott

How to get Azure service pricing details programmatically?

Can anybody please tell me how can I programmatically get Azure service pricing details (pricing for Compute, Data Services , App Services, Network Services) from Azure website?
Does Azure provide the pricing details in JSON format?
Windows Azure does'not provide any such API as of today, although it is a much asked feature and hopefully they are working on it.
Check here:
http://feedback.windowsazure.com/forums/170030-billing/suggestions/1143971-billing-usage-api#comments
The only way for now could be to build your own data store with details mentioned here : http://azure.microsoft.com/en-us/pricing/calculator/
Unit wise price will be mentioned in the usage data csv, but unfortunately the only way for now is to download this csv for your subscription here: https://account.windowsazure.com/Subscriptions
Azure now provides API's to get usage and billing data. You can have a look at this blog which gives an overview of these API's and the feedback form here which contains links to some useful pages.
In summary use the following API's to get usage and billing data:
Resource usage
Resource ratecard
Not sure, if i am too late to answer.
I was looking for the same thing and stumble upon this post on stack overflow: Azure pricing calculator api. I was able to generate JSON string using this git hub repo: https://github.com/Azure-Samples/billing-dotnet-ratecard-api.
Hope this helps!
Late to the party but I found myself looking for this and nothing here got me what I wanted. Then I found this https://learn.microsoft.com/en-us/rest/api/cost-management/retail-prices/azure-retail-prices
It is pretty straight forward. Add the reference to the Json.NET .NET 4.0 to your project It shows up in your references as Newtonsoft.Json
//You will need to add these usings
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Net.Http;
private void btnGetRates_Click(object sender, EventArgs e)
{
string strUrl = "https://prices.azure.com/api/retail/prices?$filter=serviceName eq 'Virtual Machines' and skuName eq 'E64 v4' and reservationTerm eq '3 Years'";
string response = GetDataFromAPI(strUrl);
// Here is am turning the Json response into a datatable and then loading that into a DataGridView.
//You can use the Json response any way you wish
DataTable dt = Tabulate(response);
dgvAzureSKU.DataSource = null;
dgvAzureSKU.DataSource = dt;
}
public string GetDataFromAPI(string url)
{
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Accept", "application/json");
var response = httpClient.GetStringAsync(new Uri(url)).Result;
return response;
}
}
public static DataTable Tabulate(string json)
{
var jsonLinq = JObject.Parse(json);
// Find the first array using Linq
var srcArray = jsonLinq.Descendants().Where(d => d is JArray).First();
var trgArray = new JArray();
foreach (JObject row in srcArray.Children<JObject>())
{
var cleanRow = new JObject();
foreach (JProperty column in row.Properties())
{
if (column.Value is JValue) // Only include JValue types
{
cleanRow.Add(column.Name, column.Value);
}
}
trgArray.Add(cleanRow);
}
return JsonConvert.DeserializeObject<DataTable>(trgArray.ToString()); //This is what loads the data into the table
}
You can find some examples for that here https://learn.microsoft.com/en-us/azure/billing/billing-usage-rate-card-overview. Azure provides invoice, usage and ratecard APIs which can help you to do things like:
Azure spend during the month
Set up alerts
Predict bill
Pre-consumption cost analysis

How to make the cache to refresh when the XML is changed?

I am using MvcSiteMapProvider 4.6.3, MVC 4. Using DI to config the Sitemap.
this.For<System.Runtime.Caching.ObjectCache>()
.Use(s => System.Runtime.Caching.MemoryCache.Default);
this.For(typeof (ICacheProvider<>)).Use(typeof (RuntimeCacheProvider<>));
var rootCacheDependency = this.For<ICacheDependency>().Use<RuntimeFileCacheDependency>()
.Ctor<string>("fileName").Is(rootFileName);
var rootCacheDetails = this.For<ICacheDetails>().Use<CacheDetails>()
.Ctor<TimeSpan>("absoluteCacheExpiration").Is(absoluteCacheExpiration)
.Ctor<TimeSpan>("slidingCacheExpiration").Is(TimeSpan.MinValue)
.Ctor<ICacheDependency>().Is(rootCacheDependency);
var cacheDetails = new List<SmartInstance<CacheDetails>>();
var xmlSources = new List<SmartInstance<FileXmlSource>>();
How to make it automatically update the cache when the Sitemap xml is updated?
I am upgrading MvcSitemapProvider from v3 to v4.
In version 3, it seems the sitemap is automatically refreshed.
I did set the cache expiration time to be 5 min, is this causing problem?
TimeSpan absoluteCacheExpiration = TimeSpan.FromMinutes(5);
var rootCacheDetails = this.For<ICacheDetails>().Use<CacheDetails>()
.Ctor<TimeSpan>("absoluteCacheExpiration").Is(absoluteCacheExpiration)
.Ctor<TimeSpan>("slidingCacheExpiration").Is(TimeSpan.MinValue)
.Ctor<ICacheDependency>().Is(rootCacheDependency);
UPDATE
When I change the sitemap xml file the cache is not updated till 5 min the cache expire.
I am using multiple sitemap xml files.
var sitmapPath = HostingEnvironment.MapPath("~/Sitemaps");
var sitemaps = new List<string>();
if (sitmapPath != null)
{
sitemaps.AddRange(Directory.GetFiles(sitmapPath, "*.sitemap"));
}
foreach (var sitemapFileName in sitemaps)
{
var cacheDependencie =
this.For<ICacheDependency>()
.Use<RuntimeFileCacheDependency>()
.Ctor<string>("fileName")
.Is(sitemapFileName);
cacheDetails.Add(this.For<ICacheDetails>().Use<CacheDetails>()
.Ctor<TimeSpan>("absoluteCacheExpiration").Is(absoluteCacheExpiration)
.Ctor<TimeSpan>("slidingCacheExpiration").Is(TimeSpan.MinValue)
.Ctor<ICacheDependency>().Is(cacheDependencie));
xmlSources.Add(this.For<IXmlSource>().Use<FileXmlSource>()
.Ctor<string>("fileName").Is(sitemapFileName));
}
Will this be the reason it's not working?
I don't see a problem with the code you posted. However, it is the RuntimeFileCacheDependency that will make it reload when the XML is changed.
The RuntimeFileCacheDependency expects the fileName argument to be an absolute path. So you must convert it using HostingEnvironment.MapPath before providing it to the RuntimeFileCacheDependency constructor.
var rootFileName = HostingEnvironment.MapPath("~/root.sitemap");
Response to Your Update
The purpose of the cacheDetails object is to specify the caching policy for a single SiteMapBuilderSet instance. If you look further down in the (original) DI module, notice that the variable is passed to the constructor of this class.
// Configure the builder sets
this.For<ISiteMapBuilderSetStrategy>().Use<SiteMapBuilderSetStrategy>()
.EnumerableOf<ISiteMapBuilderSet>().Contains(x =>
{
x.Type<SiteMapBuilderSet>()
.Ctor<string>("instanceName").Is("default")
.Ctor<bool>("securityTrimmingEnabled").Is(securityTrimmingEnabled)
.Ctor<bool>("enableLocalization").Is(enableLocalization)
.Ctor<bool>("visibilityAffectsDescendants").Is(visibilityAffectsDescendants)
.Ctor<bool>("useTitleIfDescriptionNotProvided").Is(useTitleIfDescriptionNotProvided)
.Ctor<ISiteMapBuilder>().Is(builder)
.Ctor<ICacheDetails>().Is(cacheDetails); // <- caching specified here explicitly.
});
This is what is used to expire the cache, but it is a completely separate mechanism from the part that specifies to use multiple files to build a SiteMap:
// Register the sitemap node providers
var siteMapNodeProvider = this.For<ISiteMapNodeProvider>().Use<CompositeSiteMapNodeProvider>()
.EnumerableOf<ISiteMapNodeProvider>().Contains(x =>
{
x.Type<XmlSiteMapNodeProvider>()
.Ctor<bool>("includeRootNode").Is(true)
.Ctor<bool>("useNestedDynamicNodeRecursion").Is(false)
.Ctor<IXmlSource>().Is(rootXmlSource);
// NOTE: Each additional XmlSiteMapNodeProvider instance for the same SiteMap instance must
// specify includeRootNode as "false"
x.Type<XmlSiteMapNodeProvider>()
.Ctor<bool>("includeRootNode").Is(false)
.Ctor<bool>("useNestedDynamicNodeRecursion").Is(false)
.Ctor<IXmlSource>().Is(childXmlSource1);
x.Type<XmlSiteMapNodeProvider>()
.Ctor<bool>("includeRootNode").Is(false)
.Ctor<bool>("useNestedDynamicNodeRecursion").Is(false)
.Ctor<IXmlSource>().Is(childXmlSource2);
// Add additional XmlSiteMapNodeProviders here (with includeRootNode as "false")...
// You only need this if you intend to use MvcSiteMapNodeAttribute in your application
x.Type<ReflectionSiteMapNodeProvider>()
.Ctor<IEnumerable<string>>("includeAssemblies").Is(includeAssembliesForScan)
.Ctor<IEnumerable<string>>("excludeAssemblies").Is(new string[0]);
});
// Register the sitemap builders
var builder = this.For<ISiteMapBuilder>().Use<SiteMapBuilder>()
.Ctor<ISiteMapNodeProvider>().Is(siteMapNodeProvider);
This is how to specify multiple XML files for a single SiteMap, but it is also possible to make each XML file into its own SiteMap instance by passing each instance of XmlSiteMapNodeProvider to a separate SiteMapBuilder and a separate SiteMapBuilderSet as described in Multiple SiteMaps in One Application.
IMPORTANT: For multiple XML files to work on a single SiteMap instance, you must specify the same key for the root node of each SiteMap as shown at the bottom of this answer. But you cannot specify a node representing the same controller action in more than one XML file (other than the root node).
If you need more flexibility than this, I would suggest implementing your own XmlSiteMapNodeProvider or abandoning the idea of using XML altogether, since using ISiteMapNodeProvider or IDynamicNodeProvider is much more flexible.
Now, back to the caching. If you are indeed using multiple XML files in the same SiteMap instance, you need to use a RuntimeCompositeCacheDependency so each of the files will be considered a dependency for the same cache, but you must use a single instance of CacheDetails.
var rootCacheDependency =
this.For<ICacheDependency>().Use<RuntimeFileCacheDependency>()
.Ctor<string>("fileName").Is(rootAbsoluteFileName);
var childCacheDependency1 =
this.For<ICacheDependency>().Use<RuntimeFileCacheDependency>()
.Ctor<string>("fileName").Is(childAbsoluteFileName1);
var childCacheDependency2 =
this.For<ICacheDependency>().Use<RuntimeFileCacheDependency>()
.Ctor<string>("fileName").Is(childAbsoluteFileName2);
var cacheDependency =
this.For<ICacheDependency>().Use<RuntimeCompositeCacheDependency>()
.Ctor<ICacheDependency[]>().Is(new ICacheDependency[]
{
(ICacheDependency)rootCacheDependency,
(ICacheDependency)childCacheDependency1,
(ICacheDependency)childCacheDependency2
});
var cacheDetails =
this.For<ICacheDetails>().Use<CacheDetails>()
.Ctor<TimeSpan>("absoluteCacheExpiration").Is(absoluteCacheExpiration)
.Ctor<TimeSpan>("slidingCacheExpiration").Is(TimeSpan.MinValue)
.Ctor<ICacheDependency>().Is(cacheDependency);

Generating a URL to a service in ServiceStack

How would I generate a URL to a specific service defined in ServiceStack?
I want to include full or relative URLs to other endpoints as part of the response DTO. RestServiceBase contains RequestContext.AbsoluteUri, but that is entirely dependent on the request.
Reverse Routing
The Reverse Routing section in the wiki shows how to use extension methods on a popualated Request DTO to generate relative and absolute URI's:
If you use [Route] metadata attributes (as opposed to the Fluent API) you will be able to generate strong-typed URI's using just the DTOs, letting you create urls outside of ServiceStack web framework as done with .NET Service Clients using the ToUrl(HttpMethod) and ToAbsoluteUri(HttpMethod), e.g:
[Route("/reqstars/search", "GET")]
[Route("/reqstars/aged/{Age}")]
public class SearchReqstars : IReturn<ReqstarsResponse>
{
public int? Age { get; set; }
}
var relativeUrl = new SearchReqstars { Age = 20 }.ToGetUrl();
var absoluteUrl = new SearchReqstars { Age = 20 }.ToAbsoluteUri();
relativeUrl.Print(); //= /reqstars/aged/20
absoluteUrl.Print(); //= http://www.myhost.com/reqstars/aged/20
The Email Contacts demo shows an example of using the above Reverse Routing extension methods to populate routes for HTML Forms and Links in Razor Views.
Other Reverse Routing Extension methods
new RequestDto().ToPostUrl();
new RequestDto().ToPutUrl();
new RequestDto().ToDeleteUrl();
new RequestDto().ToOneWayUrl();
new RequestDto().ToReplyUrl();
Accessing Http Request
You can also inspect the incoming underlying httpRequest with:
var httpReq = base.RequestContext.Get<IHttpRequest>();
As well as the underlying ASP.NET (or HttpListener) Request object with:
var aspNetReq = httpReq.OriginalRequest;
They should contain additional properties that should be more useful.

Resources