Flyweight pattern in this simple net core Api uses more memory ram - asp.net-core

I'm trying to aplicate Flyweight method pattern in a simple .net core Api to see how much memory is saved compared to not using the pattern.
I have two methods, the first one creates 5000 objects without uses the pattern and the another creates 5000 object using the pattern. After each of them create the objects, then they call a method that returns the current memory used by the App.
public class MemoryService : IMemoryService
{
private readonly TreeFactory _treeFactory;
public MemoryService()
{
_treeFactory = new TreeFactory();
}
//create without pattern
public long SetObjectsMemory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < 5000; i++)
{
var tree = new Tree()
{
Id = new Random().Next(1, 9999999),
Part = new PartTree()
{
Name = "Nameany",
Bark = "Barkany",
Color = "Colorany"
}
};
trees.Add(tree);
};
return Utilities.GetCurrentMemoryUsed();
}
//crete with flyweight pattern
public long SetObjectsMemoryFactory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < 5000; i++)
{
var tree = new Tree()
{
Id = new Random().Next(1, 9999999),
Part = _treeFactory.GetPartTree("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
}
I use the pattern like a class that uses a list of Parts and return a part object if exists.
public class TreeFactory
{
private static List<PartTree> _parts;
public TreeFactory() {
_parts = new List<PartTree>();
}
public PartTree GetPartTree(string name, string bark, string color)
{
if (_parts.Any(x => x.Name == name && x.Bark == bark && x.Color == color))
{
return _parts.Where(x => x.Name == name && x.Bark == bark && x.Color == color).FirstOrDefault();
}
else {
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
}
}
The way to get the current memory used by the App is using Process of this way (in Utilities class):
public static long GetCurrentMemoryUsed() {
Int64 memory;
using (Process proc = Process.GetCurrentProcess())
{
memory = proc.PrivateMemorySize64 / (1024 * 1024);
}
return memory;
}
And in my Startup i inject the MemoryService like a Singleton. In the controller i use 3 methods for call the functions:
[HttpGet, Route(nameof(WeatherForecastController.GenerateMemory))]
public IActionResult GenerateMemory()
{
var total=_memoryService.SetObjectsMemory();
return Ok(total);
}
[HttpGet, Route(nameof(WeatherForecastController.GenerateLiftMemory))]
public IActionResult GenerateLiftMemory()
{
var total = _memoryService.SetObjectsMemoryFactory();
return Ok(total);
}
[HttpGet, Route(nameof(WeatherForecastController.GetMemory))]
public IActionResult GetMemory()
{
var total = Utilities.GetCurrentMemoryUsed();
return Ok(total);
}
The problem is: When i call in the navigator the method in controller without pattern (/weatherforecast/GenerateMemory), then this returns (current)+2mb, but when i call the method
with pattern (/weatherforecast/GenerateLiftMemory) this returns (current)+3mb.
Why the method with pattern flyweight returns more used MB (growing) than the methods without the pattern ??
The repository with the code for test it. Gitlab repository memory api

The code which uses TreeFactory consumes more memory because its GetPartTree method called many times in a loop so as Linq methods Any and Where inside it. Both of these methods create additional Iterator objects under the hood in order to iterate through the collection and it causes additional memory consumption.
I wrote simple benchmark using BenchmarkDotNet with more options to demonstrate the issue
Extended MemoryService
public class MemoryService : IMemoryService
{
private const int TreeCount = 50000;
private readonly TreeFactory _treeFactory;
public MemoryService()
{
_treeFactory = new TreeFactory();
}
//crea objetos en memoria sin patrones
public decimal SetObjectsMemory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = new PartTree()
{
Name = "Nameany",
Bark = "Barkany",
Color = "Colorany"
}
};
trees.Add(tree);
};
return Utilities.GetCurrentMemoryUsed();
}
//crea objetos en memoria usando patron flyweight
public decimal SetObjectsMemoryFactory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = _treeFactory.GetPartTree("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
public decimal SetObjectsMemoryFactoryImproved()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = _treeFactory.GetPartTreeImproved("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
//crea objetos en memoria usando patron flyweight
public decimal SetObjectsMemoryFactoryWithoutLambda()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = _treeFactory.GetPartTreeWithoutLambda("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
}
Extended TreeFactory
public class TreeFactory
{
private static List<PartTree> _parts;
public TreeFactory()
{
_parts = new List<PartTree>();
}
public PartTree GetPartTree(string name, string bark, string color)
{
if (_parts.Any(x => x.Name == name && x.Bark == bark && x.Color == color))
{
return _parts.Where(x => x.Name == name && x.Bark == bark && x.Color == color).FirstOrDefault();
}
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
public PartTree GetPartTreeImproved(string name, string bark, string color)
{
var existingPart = _parts.Where(x => x.Name == name && x.Bark == bark && x.Color == color).FirstOrDefault();
if (existingPart != null)
return existingPart;
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
public PartTree GetPartTreeWithoutLambda(string name, string bark, string color)
{
for (int i = 0; i < _parts.Count; i++)
{
var x = _parts[i];
if (x.Name == name && x.Bark == bark && x.Color == color)
return x;
}
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
}
Benchmark in a separate console project
class Program
{
static void Main(string[] args)
{
var result = BenchmarkRunner.Run<MemoryBenchmark>();
}
}
[MemoryDiagnoser]
public class MemoryBenchmark
{
private IMemoryService memoryService;
[GlobalSetup]
public void Setup()
{
memoryService = new MemoryService();
}
[Benchmark]
public object SimpleTrees()
{
var trees = memoryService.SetObjectsMemory();
return trees;
}
[Benchmark]
public object FlyTrees()
{
var trees = memoryService.SetObjectsMemoryFactory();
return trees;
}
[Benchmark]
public object FlyTreesImproved()
{
var trees = memoryService.SetObjectsMemoryFactoryImproved();
return trees;
}
[Benchmark]
public object FlyTreesWithoutLambda()
{
var trees = memoryService.SetObjectsMemoryFactoryWithoutLambda();
return trees;
}
}
And its results
Method
Mean
Error
StdDev
Gen 0
Gen 1
Gen 2
Allocated
SimpleTrees
9.040 ms
0.1804 ms
0.2346 ms
718.7500
453.1250
265.6250
4.44 MB
FlyTrees
19.701 ms
0.1716 ms
0.1521 ms
2500.0000
906.2500
437.5000
15.88 MB
FlyTreesImproved
18.075 ms
0.2869 ms
0.2684 ms
1781.2500
625.0000
312.5000
10.92 MB
FlyTreesWithoutLambda
4.919 ms
0.0273 ms
0.0242 ms
421.8750
281.2500
281.2500
2.53 MB

Related

Read Data attributes or Custom Attributes in SQL server from string

I want in SQL prepared dynamic query based on the shortcode.
For Eg.
DECLARE #ShortCode VARCHAR(MAX)
SET #ShortCode = '[User data="Name" data="MobileNumber"]';
User = table name
Name = User table field
MobileNumber = User table field
Query output be like
SELECT [Name],[MobileNumber] FROM [dbo].[User]
SET #ShortCode = '[Country data="Name" ID="1"]';
Country = table name
Name = Country table field
ID = User table field
Query output be like
SELECT [Name] FROM [dbo].[Country] WHERE [ID] = 1
How to extract all data attributes values and how to get User in the []
This functionality is done in C#
Here My c# code
// Model class
public class ShortCodeResult
{
public Guid? ID { get; set; }
public string TableName { get; set; }
public bool IsValidShortCode { get; set; }
public string Message { get; set; }
public Dictionary<string,object> KeyValue { get; set; }
public ShortCodeResult() {
KeyValue = new Dictionary<string, object>();
ID = Guid.NewGuid();
}
}
//Regex Filter
public class RegexFilter
{
private string oPattern = #"(\w+)=[\""]([a-zA-Z0-9_.:\""]+)";
public ShortCodeResult GetShortCodeValues(string Code)
{
var oShortCodeModel = new ShortCodeResult();
var oRegex = new Regex(oPattern, RegexOptions.IgnoreCase);
var oTableNameRegex = Regex.Match(Code, #"\b[A-Za-z]+\b", RegexOptions.Singleline).Value;
var lstMatchCollection = oRegex.Matches(Code).Cast<Match>().Where(x=>x.Value.StartsWith("data")).ToList();
if (lstMatchCollection != null && lstMatchCollection.Count > 0)
{
for (int i = 0; i < lstMatchCollection.Count; i++)
{
var oSelected = new Regex("[^=]+$").Match(Convert.ToString(lstMatchCollection[i]));
if (oSelected != null)
{
oShortCodeModel.KeyValue.Add(i.ToString(), oSelected.Value.Trim('"'));
}
}
}
oShortCodeModel.TableName = oTableNameRegex;
return oShortCodeModel;
}
}
//HtmlHelper Extension
public static MvcHtmlString RenderShortCode(this HtmlHelper htmlHelper, string IdOrExprssion)
{
#region Get short code data
var oShortCode = ShortCodeHelper.GetShortCode(IdOrExprssion);
#endregion
var oMvcHtmlString = new MvcHtmlString(IdOrExprssion);
var oRegexFilter = new RegexFilter();
var shortCodeModel = oRegexFilter.GetShortCodeValues(oShortCode.Expression);
var ostringBuilder = new StringBuilder();
if (!string.IsNullOrEmpty(shortCodeModel.TableName))
{
ostringBuilder.AppendLine("SELECT ");
ostringBuilder.AppendLine((shortCodeModel.KeyValue.Count > 0 ? string.Join(",", shortCodeModel.KeyValue.Select(x => x.Value)) : "*"));
ostringBuilder.AppendLine(" FROM ");
ostringBuilder.AppendLine(oShortCode.TableName);
ostringBuilder.AppendLine(" WITH(NOLOCK) ");
if (oShortCode.FilterCode.Count() > 0)
{
ostringBuilder.AppendLine("WHERE ");
foreach (var filterCode in oShortCode.FilterCode)
{
ostringBuilder.AppendLine(filterCode.FilterColumnName);
ostringBuilder.AppendLine(filterCode.Operator);
ostringBuilder.AppendLine(filterCode.FilterColumnValue);
}
}
}
var oDyanamicData = DBHelper.GetDataTable(ostringBuilder.ToString(), System.Data.CommandType.Text, new List<SqlParameter>());
if (oDyanamicData != null)
{
if (oShortCode.IsHtmlRender)
{
for (int i = 0; i < oDyanamicData.Rows.Count; i++)
{
for (int j = 0; j < oDyanamicData.Columns.Count; j++)
{
string key = Convert.ToString(oDyanamicData.Columns[j]);
string value = Convert.ToString(oDyanamicData.Rows[i].ItemArray[j]);
if (oShortCode.DisplayCode.Count > 0)
{
var displayCode = oShortCode.DisplayCode.FirstOrDefault(x => x.DisplayColumnName == key);
if (displayCode != null && !string.IsNullOrEmpty(displayCode?.ReplaceKey))
{
oShortCode.DefinedHtml = oShortCode.DefinedHtml.Replace(displayCode.ReplaceKey, value);
}
}
}
}
return new MvcHtmlString(oShortCode.DefinedHtml);
}
else
{
string key = string.Empty, value = string.Empty;
#region For Json
List<JObject> dataList = new List<JObject>();
for (int i = 0; i < oDyanamicData.Rows.Count; i++)
{
JObject eachRowObj = new JObject();
for (int j = 0; j < oDyanamicData.Columns.Count; j++)
{
key = Convert.ToString(oDyanamicData.Columns[j]);
value = Convert.ToString(oDyanamicData.Rows[i].ItemArray[j]);
eachRowObj.Add(key, value);
}
dataList.Add(eachRowObj);
}
return new MvcHtmlString(Newtonsoft.Json.JsonConvert.SerializeObject(dataList));
#endregion
}
}
return oMvcHtmlString;
}
Can anyone help me solved above in SQL server or prepared query in store procedure

Swashbuckle Swagger - Pulling information from Attributes and putting it into the Schema definition

I am trying to have pull the DisplayAttribute and the DescriptionAttribute from parts of the Swagger Model. For example I may have a Body Parameter which has properties with attributes, which I would also want to be generated in the swagger.json and visible in SwaggerUI.
So far I think the approach that should work would be using a custom filter with swashbuckle. I got a proof of concept using the IParameterFilter which displays the description attribute, not sure if another filter would be better.
Issues:
Finding the key for the schemaRegistry fails for some types, like list.
Need to get the key for the parameter to be generated the same as swagger.
Might need recursion to loop through child properties that contain complex objects.
public class SwaggerParameterFilter : IParameterFilter
{
private SchemaRegistrySettings _settings;
private SchemaIdManager _schemaIdManager;
public SwaggerParameterFilter(SchemaRegistrySettings settings = null)
{
this._settings = settings ?? new SchemaRegistrySettings();
this._schemaIdManager = new SchemaIdManager(this._settings.SchemaIdSelector);
}
public void Apply(IParameter parameter, ParameterFilterContext context)
{
try
{
if (context.ApiParameterDescription?.ModelMetadata?.Properties == null) return;
if (parameter is BodyParameter bodyParameter)
{
string idFor = _schemaIdManager.IdFor(context.ApiParameterDescription.Type);
var schemaRegistry = (SchemaRegistry)context.SchemaRegistry;
//not perfect, crashes with some cases
var schema = schemaRegistry.Definitions[idFor];
//bodyParameter.Schema, this doesn't seem right, no properties
foreach (var modelMetadata in context.ApiParameterDescription.ModelMetadata.Properties)
{
if (modelMetadata is DefaultModelMetadata defaultModelMetadata)
{
//not sure right now how to get the right key for the schema.Properties...
var name = defaultModelMetadata.Name;
name = Char.ToLowerInvariant(name[0]) + name.Substring(1);
if (schema.Properties.ContainsKey(name))
{
var subSchema = schema.Properties[name];
var attributes = defaultModelMetadata.Attributes.Attributes.Select(x => (Attribute)x);
var descriptionAttribute = (DescriptionAttribute)attributes.FirstOrDefault(x => x is DescriptionAttribute);
if (descriptionAttribute != null)
subSchema.Description = descriptionAttribute.Description;
}
}
}
}
}
catch (Exception e)
{
//eat because above is broken
}
}
}
Edit add looping.
public class SwaggerParameterFilter : IParameterFilter
{
private SchemaRegistrySettings _settings;
private SchemaIdManager _schemaIdManager;
public SwaggerParameterFilter(SchemaRegistrySettings settings = null)
{
this._settings = settings ?? new SchemaRegistrySettings();
this._schemaIdManager = new SchemaIdManager(this._settings.SchemaIdSelector);
}
public void Apply(IParameter parameter, ParameterFilterContext context)
{
try
{
if (context.ApiParameterDescription?.ModelMetadata?.Properties == null) return;
//Only BodyParameters are complex and stored in the schema
if (parameter is BodyParameter bodyParameter)
{
var idFor = _schemaIdManager.IdFor(context.ApiParameterDescription.Type);
//not perfect, crashes with some cases
var schema = context.SchemaRegistry.Definitions[idFor];
UpdateSchema(schema, (SchemaRegistry) context.SchemaRegistry, context.ApiParameterDescription.ModelMetadata);
}
}
catch (Exception e)
{
//eat because above is broken
}
}
private void UpdateSchema(Schema schema, SchemaRegistry schemaRegistry, ModelMetadata modelMetadata)
{
if (schema.Ref != null)
{
var schemaReference = schema.Ref.Replace("#/definitions/", "");
UpdateSchema(schemaRegistry.Definitions[schemaReference], schemaRegistry, modelMetadata);
return;
}
if (schema.Properties == null) return;
foreach (var properties in modelMetadata.Properties)
{
if (properties is DefaultModelMetadata defaultModelMetadata)
{
//not sure right now how to get the right key for the schema.Properties...
var name = defaultModelMetadata.Name;
name = Char.ToLowerInvariant(name[0]) + name.Substring(1);
if (schema.Properties.ContainsKey(name) == false) return;
var subSchema = schema.Properties[name];
var attributes = defaultModelMetadata.Attributes.Attributes.Select(x => (Attribute) x).ToList();
var descriptionAttribute =
(DescriptionAttribute) attributes.FirstOrDefault(x => x is DescriptionAttribute);
if (descriptionAttribute != null)
subSchema.Description = descriptionAttribute.Description;
var displayAttribute = (DisplayAttribute) attributes.FirstOrDefault(x => x is DisplayAttribute);
if (displayAttribute != null)
subSchema.Title = displayAttribute.Name;
if (modelMetadata.ModelType.IsPrimitive) return;
UpdateSchema(subSchema, schemaRegistry, defaultModelMetadata);
}
}
}
}
Operation Filter
public class SwaggerOperationFilter : IOperationFilter
{
private SchemaRegistrySettings _settings;
private SchemaIdManager _schemaIdManager;
private IModelMetadataProvider _metadataProvider;
public SwaggerOperationFilter(IModelMetadataProvider metadataProvider, SchemaRegistrySettings settings = null)
{
this._metadataProvider = metadataProvider;
this._settings = settings ?? new SchemaRegistrySettings();
this._schemaIdManager = new SchemaIdManager(this._settings.SchemaIdSelector);
}
public void Apply(Operation operation, OperationFilterContext context)
{
try
{
foreach (var paramDescription in context.ApiDescription.ParameterDescriptions)
{
if (paramDescription?.ModelMetadata?.Properties == null)
{
continue;
}
if (paramDescription.ModelMetadata.ModelType.IsPrimitive)
{
continue;
}
if (paramDescription.ModelMetadata.ModelType == typeof(string))
{
continue;
}
var idFor = _schemaIdManager.IdFor(paramDescription.Type);
var schema = context.SchemaRegistry.Definitions[idFor];
UpdateSchema(schema, (SchemaRegistry)context.SchemaRegistry, paramDescription.ModelMetadata);
}
}
catch (Exception e)
{
//eat because above is broken
}
}
private void UpdateSchema(Schema schema, SchemaRegistry schemaRegistry, ModelMetadata modelMetadata)
{
if (schema.Ref != null)
{
var schemaReference = schema.Ref.Replace("#/definitions/", "");
UpdateSchema(schemaRegistry.Definitions[schemaReference], schemaRegistry, modelMetadata);
return;
}
if (schema.Type == "array")
{
if (schema.Items.Ref != null)
{
var schemaReference = schema.Items.Ref.Replace("#/definitions/", "");
var modelTypeGenericTypeArgument = modelMetadata.ModelType.GenericTypeArguments[0];
modelMetadata = _metadataProvider.GetMetadataForType(modelTypeGenericTypeArgument);
UpdateSchema(schemaRegistry.Definitions[schemaReference], schemaRegistry, modelMetadata);
}
return;
}
if (schema.Properties == null) return;
foreach (var properties in modelMetadata.Properties)
{
if (properties is DefaultModelMetadata defaultModelMetadata)
{
//not sure right now how to get the right key for the schema.Properties...
var name = defaultModelMetadata.Name;
name = Char.ToLowerInvariant(name[0]) + name.Substring(1);
if (schema.Properties.ContainsKey(name) == false) return;
var subSchema = schema.Properties[name];
var attributes = defaultModelMetadata.Attributes.Attributes.Select(x => (Attribute)x).ToList();
var descriptionAttribute =
(DescriptionAttribute)attributes.FirstOrDefault(x => x is DescriptionAttribute);
if (descriptionAttribute != null)
subSchema.Description = descriptionAttribute.Description;
var displayAttribute = (DisplayAttribute)attributes.FirstOrDefault(x => x is DisplayAttribute);
if (displayAttribute != null)
subSchema.Title = displayAttribute.Name;
if (defaultModelMetadata.ModelType.IsPrimitive) return;
UpdateSchema(subSchema, schemaRegistry, defaultModelMetadata);
}
}
}
}
So after some troubleshooting this seems to work for me but may need modification for other cases.
public class SwashbuckleAttributeReaderDocumentFilter : IDocumentFilter
{
private readonly SchemaIdManager _schemaIdManager;
private readonly IModelMetadataProvider _metadataProvider;
private List<string> _updatedSchemeList;
public SwashbuckleAttributeReaderDocumentFilter(IModelMetadataProvider metadataProvider, SchemaRegistrySettings settings = null)
{
_metadataProvider = metadataProvider;
var registrySettings = settings ?? new SchemaRegistrySettings();
_schemaIdManager = new SchemaIdManager(registrySettings.SchemaIdSelector);
}
public void Apply(SwaggerDocument swaggerDoc, DocumentFilterContext context)
{
_updatedSchemeList = new List<string>();
foreach (var apiDescription in context.ApiDescriptions)
{
foreach (var responseTypes in apiDescription.SupportedResponseTypes)
{
ProcessModelMetadata(context, responseTypes.ModelMetadata);
}
foreach (var paramDescription in apiDescription.ParameterDescriptions)
{
ProcessModelMetadata(context, paramDescription.ModelMetadata);
}
}
}
private void ProcessModelMetadata(DocumentFilterContext context, ModelMetadata currentModelMetadata)
{
if (currentModelMetadata?.Properties == null)
{
return;
}
if (currentModelMetadata.ModelType.IsValueType)
{
return;
}
if (currentModelMetadata.ModelType == typeof(string))
{
return;
}
if (currentModelMetadata.ModelType.IsGenericType)
{
foreach (var modelType in currentModelMetadata.ModelType.GenericTypeArguments)
{
var modelMetadata = _metadataProvider.GetMetadataForType(modelType);
UpdateSchema(context.SchemaRegistry, modelMetadata);
}
}
else if (currentModelMetadata.IsCollectionType)
{
var modelType = currentModelMetadata.ModelType.GetElementType();
var modelMetadata = _metadataProvider.GetMetadataForType(modelType);
UpdateSchema(context.SchemaRegistry, modelMetadata);
}
else
{
UpdateSchema(context.SchemaRegistry, currentModelMetadata);
}
}
public static void SetSchema(Schema schema, ModelMetadata modelMetadata)
{
if (!(modelMetadata is DefaultModelMetadata metadata)) return;
var attributes = GetAtributes(metadata);
SetDescription(attributes, schema);
SetTitle(attributes, schema);
}
private static List<Attribute> GetAtributes(DefaultModelMetadata modelMetadata)
{
return modelMetadata.Attributes.Attributes.Select(x => (Attribute)x).ToList();
}
private static void SetTitle(List<Attribute> attributes, Schema schema)
{
//LastOrDefault because we want the attribute from the dervived class.
var displayAttribute = (DisplayNameAttribute)attributes.LastOrDefault(x => x is DisplayNameAttribute);
if (displayAttribute != null)
schema.Title = displayAttribute.DisplayName;
}
private static void SetDescription(List<Attribute> attributes, Schema schema)
{
//LastOrDefault because we want the attribute from the dervived class. not sure if this works.
var descriptionAttribute = (DescriptionAttribute)attributes.LastOrDefault(x => x is DescriptionAttribute);
if (descriptionAttribute != null)
schema.Description = descriptionAttribute.Description;
}
private void UpdateSchema(ISchemaRegistry schemaRegistry, ModelMetadata modelMetadata, Schema schema = null)
{
if (modelMetadata.ModelType.IsValueType) return;
if (modelMetadata.ModelType == typeof(string)) return;
var idFor = _schemaIdManager.IdFor(modelMetadata.ModelType);
if (_updatedSchemeList.Contains(idFor))
return;
if (schema == null || schema.Ref != null)
{
if (schemaRegistry.Definitions.ContainsKey(idFor) == false) return;
schema = schemaRegistry.Definitions[idFor];
}
_updatedSchemeList.Add(idFor);
SetSchema(schema, modelMetadata);
if (schema.Type == "array")//Array Schema
{
var metaData = _metadataProvider.GetMetadataForType(modelMetadata.ModelType.GenericTypeArguments[0]);
UpdateSchema(schemaRegistry, metaData);
}
else//object schema
{
if (schema.Properties == null)
{
return;
}
foreach (var properties in modelMetadata.Properties)
{
if (!(properties is DefaultModelMetadata defaultModelMetadata))
{
continue;
}
var name = ToLowerCamelCase(defaultModelMetadata.Name);
if (schema.Properties.ContainsKey(name) == false)
{
//when this doesn't match the json object naming.
return;
}
var subSchema = schema.Properties[name];
SetSchema(subSchema, defaultModelMetadata);
UpdateSchema(schemaRegistry, defaultModelMetadata, subSchema);
}
}
}
private static string ToLowerCamelCase(string inputString)
{
if (inputString == null) return null;
if (inputString == string.Empty) return string.Empty;
if (char.IsLower(inputString[0])) return inputString;
return inputString.Substring(0, 1).ToLower() + inputString.Substring(1);
}
}

managed c++ classes crash in create_task

Basically, what is happening is when trying to change a variable of a Managed class (UWP), it crashes. Additionally, it seems to only crash if I try modifying a variable which is created with the app namespace. In other words, if I create a new namspace and managed class, I can modify variables just fine.
void ASynTaskCategories(void)
{
concurrency::task_completion_event<Platform::String^> taskDone;
MainPage^ rootPage = this;
UberSnip::HELPER::ASYNC_RESPONSE^ responseItem = ref new UberSnip::HELPER::ASYNC_RESPONSE();
create_task([taskDone, responseItem, rootPage]() -> Platform::String^
{
//UBERSNIP API 0.4
UberSnip::UBERSNIP_CLIENT* UberSnipAPI = new UberSnip::UBERSNIP_CLIENT();
UberSnipAPI->Http->RequestURL = "http://api.ubersnip.com/categories.php";
UberSnipAPI->Http->request();
taskDone.set(UberSnipAPI->Client->BodyResponse);
responseItem->Body = UberSnipAPI->Client->BodyResponse;
return "(done)";
}).then([taskDone, responseItem, rootPage](Platform::String^ BodyResponse) {
Platform::String^ BR = responseItem->Body;
cJSON* cats = cJSON_Parse(_string(BR));
cats = cats->child;
int *cat_count = new int(cJSON_GetArraySize(cats));
rootPage->Categories->Clear();
GENERIC_ITEM^ all_item = ref new GENERIC_ITEM();
all_item->Title = "All";
rootPage->Categories->Append(all_item);
for (int i = 0; i < *cat_count; i++) {
cJSON* cat = new cJSON();
cat = cJSON_GetArrayItem(cats, i);
string *track_title = new string(cJSON_GetObjectItem(cat, "name")->valuestring);
GENERIC_ITEM gitem;
gitem.Title = "Hi";
GENERIC_ITEM^ ubersnipCategory = ref new GENERIC_ITEM();
ubersnipCategory->Title = _String(*track_title);
rootPage->Categories->Append(ubersnipCategory);
}
});
This does not crash
UberSnipAPI->Http->RequestURL = "http://api.ubersnip.com/categories.php";
but this one does
all_item->Title = "All";
I am almost positive it has something to do with it being in the apps default namespace and it being accessed outside of the main thread ... At least that's what it seems like as that's really the only difference besides the actual class.
This is what GENERIC_ITEM looks like.
[Windows::UI::Xaml::Data::Bindable]
public ref class GENERIC_ITEM sealed {
private:
Platform::String^ _title = "";
Platform::String^ _description;
Windows::UI::Xaml::Media::ImageSource^ _Image;
event PropertyChangedEventHandler^ _PropertyChanged;
void OnPropertyChanged(Platform::String^ propertyName)
{
PropertyChangedEventArgs^ pcea = ref new PropertyChangedEventArgs(propertyName);
_PropertyChanged(this, pcea);
}
public:
GENERIC_ITEM() {
};
property Platform::String^ Title {
Platform::String^ get() {
return this->_title;
}
void set(Platform::String^ val) {
this->_title = val;
OnPropertyChanged("Title");
}
}
property Platform::String^ Description {
Platform::String^ get() {
return this->_description;
}
void set(Platform::String^ val) {
this->_description = val;
OnPropertyChanged("Description");
}
}
void SetImage(Platform::String^ path)
{
Windows::Foundation::Uri^ uri = ref new Windows::Foundation::Uri(path);
_Image = ref new Windows::UI::Xaml::Media::Imaging::BitmapImage(uri);
}
};
I know there is no issue with the class because it works perfectly fine if I run this exact same code on the initial thread.
Any suggestions? Thanks! :D
Figured it out after several hours! In case someone else is having this issue, all you must do is use the Dispatcher to run code on the UI that is not available outside of the UI thread.
void loadCats(UberSnip::HELPER::ASYNC_RESPONSE^ responseItem, MainPage^ rootPage) {
Platform::String^ BR = responseItem->Body;
cJSON* cats = cJSON_Parse(_string(BR));
cats = cats->child;
int *cat_count = new int(cJSON_GetArraySize(cats));
rootPage->Categories->Clear();
GENERIC_ITEM^ all_item = ref new GENERIC_ITEM();
all_item->Title = "All";
rootPage->Categories->Append(all_item);
for (int i = 0; i < *cat_count; i++) {
cJSON* cat = new cJSON();
cat = cJSON_GetArrayItem(cats, i);
string *track_title = new string(cJSON_GetObjectItem(cat, "name")->valuestring);
GENERIC_ITEM gitem;
gitem.Title = "Hi";
GENERIC_ITEM^ ubersnipCategory = ref new GENERIC_ITEM();
ubersnipCategory->Title = _String(*track_title);
rootPage->Categories->Append(ubersnipCategory);
}
}
void ASyncTaskCategories(void)
{
concurrency::task_completion_event<Platform::String^> taskDone;
MainPage^ rootPage = this;
UberSnip::HELPER::ASYNC_RESPONSE^ responseItem = ref new UberSnip::HELPER::ASYNC_RESPONSE();
auto dispatch = CoreWindow::GetForCurrentThread()->Dispatcher;
auto op2 = create_async([taskDone, responseItem, rootPage, dispatch] {
return create_task([taskDone, responseItem, rootPage, dispatch]() -> Platform::String^
{
//UBERSNIP API 0.4
UberSnip::UBERSNIP_CLIENT* UberSnipAPI = new UberSnip::UBERSNIP_CLIENT();
UberSnipAPI->Http->RequestURL = "http://api.ubersnip.com/categories.php";
try{
UberSnipAPI->Http->request();
}
catch (...) {
printf("Error");
}
int err = UberSnip::UTILS::STRING::StringToAscIIChars(UberSnipAPI->Client->BodyResponse).find("__api_err");
if (err < 0) {
if (UberSnip::UTILS::STRING::StringToAscIIChars(UberSnipAPI->Client->BodyResponse).length() < 3) {
return;
}
}
taskDone.set(UberSnipAPI->Client->BodyResponse);
responseItem->Body = UberSnipAPI->Client->BodyResponse;
dispatch->RunAsync(Windows::UI::Core::CoreDispatcherPriority::High, ref new Windows::UI::Core::DispatchedHandler([=]()
{
rootPage->loadCats(responseItem, rootPage);
}));
for (int i = 0; i < 100;) {
}
return "(done)";
}).then([taskDone, responseItem, rootPage](Platform::String^ BodyResponse) {
});
});
//rootPage->loadCats(responseItem, rootPage);
}

Enum dropdownlistfor issue

I've read a possible solution to this, but would require a lot of rewriting, the possible solution is linked here, but there wouldn't be any sense to doing it that way if I am just a couple words off in my dropdownlistfor.
I'm having an issue with my dropdownlistfor as this is all new to me:
#Html.DropDownListFor(model => model.pageID, new SelectList (Enum.GetNames(typeof(PageIndex)), EnumHelper.GetSelectedItemList<PageIndex>().SelectedValue))
Trying to grab the "description" of my enum values as the drop down lists text values, then have an integer value returned to the database on POST.
Here's my enum:
public enum PageIndex : int
{
[Description("Developmental Disabilities Tip Sheet")]
ddTipSheets = 1,
[Description("Hiiiiiiiiiiiiiiiiiiii")]
Example1 = 2,
[Description("I don't know what I'm doing")]
Example2 = 3
};
and my EnumHelper:
public class EnumHelper
{
public static SelectList GetSelectedItemList<T>() where T : struct
{
T t = default(T);
if (!t.GetType().IsEnum) { throw new ArgumentNullException("Please make sure that T is of Enum Type"); }
var nameList = t.GetType().GetEnumNames();
int counter = 0;
Dictionary<int, String> myDictionary = new Dictionary<int, string>();
if (nameList != null && nameList.Length > 0)
{
foreach (var name in nameList)
{
T newEnum = (T) Enum.Parse(t.GetType(), name);
string description = getDescriptionFromEnumValue(newEnum as Enum);
if (!myDictionary.ContainsKey(counter))
{
myDictionary.Add(counter, description);
}
counter++;
}
counter = 0;
return new SelectList(myDictionary, "Key", "Value");
}
return null;
}
private static string getDescriptionFromEnumValue(Enum value)
{
DescriptionAttribute descriptionAttribute =
value.GetType()
.GetField(value.ToString())
.GetCustomAttributes(typeof(DescriptionAttribute), false)
.SingleOrDefault() as DescriptionAttribute;
return descriptionAttribute == null ?
value.ToString() : descriptionAttribute.Description;
}
}

Getting all the Term Stores in Sharepoint 2010 (web services or client-side object model)?

Is it possible with Sharepoint 2010 (not 2013!) to get a list of all the Term Stores on the site using either the web services or the client-side object model?
I know 2013 has added a library for it, but that will not help me on 2010.
If not the whole list, how do I get the Term Store ID, if I know a Term (that might or might not be in the TaxonomyHiddenList)?
Someone mentioned checking out the TaxonomyFieldType fields, so I hacked together these 2 methods. I do not know if these will work under all circumstances.
First function just returns the Term Store ID which is stored in the info of the first TaxonomyFieldType* we come over.
public static string GetDefaultTermStore(string site) {
var context = new ClientContext(site);
var fields = context.Web.Fields;
context.Load(fields, fs => fs.Include(f => f.SchemaXml, f => f.TypeAsString));
context.ExecuteQuery();
foreach (var field in fields) {
if (field.TypeAsString.StartsWith("TaxonomyFieldType")) {
var doc = XDocument.Parse(field.SchemaXml);
var node = doc.XPathSelectElement("//Name[text()='SspId']/../Value");
if (node != null && !string.IsNullOrEmpty(node.Value)) {
return node.Value;
}
}
}
throw new Exception("Term Store ID not found!");
}
The second function goes through all the fields and gets all the possible Term Store IDs and returns them in a list.
public static List<string> GetTermStores(string site) {
var context = new ClientContext(site);
var fields = context.Web.Fields;
context.Load(fields, fs => fs.Include(f => f.SchemaXml, f => f.TypeAsString));
context.ExecuteQuery();
var hashlist = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
foreach (var field in fields) {
if (field.TypeAsString.StartsWith("TaxonomyFieldType")) {
var doc = XDocument.Parse(field.SchemaXml);
var node = doc.XPathSelectElement("//Name[text()='SspId']/../Value");
if (node != null && !string.IsNullOrEmpty(node.Value)) {
if (!hashlist.Contains(node.Value)) {
hashlist.Add(node.Value);
}
}
}
}
if (hashlist.Count == 0) throw new Exception("No Term Store IDs not found!");
return hashlist.ToList();
}
Is this a correct answer to my question do anyone have a more sure way to get the IDs?
Does not seem like anyone else has a good answer for this question.
I have added the utility class I made from this below. Big block of uncommented code below for those who might need:
using Microsoft.SharePoint.Client;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web.Services.Protocols;
using System.Windows.Forms;
using System.Xml.Linq;
using System.Xml.XPath;
namespace VitaminTilKanbanPusher.Sharepoint {
public class SharepointTaxonomyAgent {
//URLS:
//http://www.novolocus.com/2012/02/06/working-with-the-taxonomyclientservice-part-1-what-fields-are-there/
//
public static void Test() {
var site = ConfigurationManager.AppSettings["VitaminSite"];
//var list = ConfigurationManager.AppSettings["VitaminList"];
//var id = GetDefaultTermStore(site);
//var ids = GetTermStores(site);
var rs = GetAllTermSetNames(site);
var ts = GetTermSetTerms(site, "Some Name");
//var ts = GetTermSetTerms(site, "Some other name");
//var term = GetTermInfo(site, "Priority");
//var term2 = GetTermInfo(site, "My term");
//var termset = GetTermSetInfo(site, "My term");
//var termsets = GetTermSets(site, "My term");
}
public static string GetDefaultTermStore(string site) {
var context = new ClientContext(site);
context.ExecutingWebRequest += ctx_MixedAuthRequest;
var fields = context.Web.Fields;
context.Load(fields, fs => fs.Include(f => f.InternalName, f => f.SchemaXml, f => f.TypeAsString));
context.ExecuteQuery();
foreach (var field in fields) {
//field.InternalName== "TaxKeyword" -> possibly default?
if (field.TypeAsString.StartsWith("TaxonomyFieldType")) {
var doc = XDocument.Parse(field.SchemaXml);
var node = doc.XPathSelectElement("//Name[text()='SspId']/../Value");
if (node != null && !string.IsNullOrEmpty(node.Value)) {
return node.Value;
}
}
}
throw new Exception("Term Store ID not found!");
}
public static List<string> GetTermStores(string site) {
var context = new ClientContext(site);
context.ExecutingWebRequest += ctx_MixedAuthRequest;
var fields = context.Web.Fields;
context.Load(fields, fs => fs.Include(f => f.SchemaXml, f => f.TypeAsString));
context.ExecuteQuery();
var hashlist = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
foreach (var field in fields) {
if (field.TypeAsString.StartsWith("TaxonomyFieldType")) {
var doc = XDocument.Parse(field.SchemaXml);
var node = doc.XPathSelectElement("//Name[text()='SspId']/../Value");
if (node != null && !string.IsNullOrEmpty(node.Value)) {
if (!hashlist.Contains(node.Value)) {
hashlist.Add(node.Value);
}
}
}
}
if (hashlist.Count == 0) throw new Exception("No Term Store IDs not found!");
return hashlist.ToList();
}
private static List<TermSet> _termSets;
public static List<TermSet> GetAllTermSetNames(string site, string onlySpecificTermSetName = null) {
if (_termSets != null) {
if (onlySpecificTermSetName == null) return _termSets;
foreach (var ts in _termSets) {
if (ts.Name.Equals(onlySpecificTermSetName, StringComparison.InvariantCultureIgnoreCase)) {
return new List<TermSet>() { ts };
}
}
return new List<TermSet>();
}
var context = new ClientContext(site);
context.ExecutingWebRequest += ctx_MixedAuthRequest;
var fields = context.Web.Fields;
context.Load(fields, fs => fs.Include(f => f.SchemaXml, f => f.TypeAsString));
context.ExecuteQuery();
var hashlist = new HashSet<string>(StringComparer.InvariantCultureIgnoreCase);
var termSets = new List<TermSet>();
TermSet theChosenTermSet = null;
foreach (var field in fields) {
if (field.TypeAsString.StartsWith("TaxonomyFieldType")) {
var ts = new TermSet();
var doc = XDocument.Parse(field.SchemaXml);
var fn = doc.Element("Field");
if (fn == null) continue;
if (fn.Attribute("DisplayName") == null) continue;
if (fn.Attribute("ID") == null) continue;
ts.Name = fn.Attribute("DisplayName").Value;
//Only 1 set?
if (onlySpecificTermSetName != null) {
if (!ts.Name.Equals(onlySpecificTermSetName, StringComparison.InvariantCultureIgnoreCase)) {
theChosenTermSet = ts;
}
}
if (fn.Attribute("Description") != null) {
ts.Description = fn.Attribute("Description").Value;
}
var node = doc.XPathSelectElement("//Name[text()='SspId']/../Value");
if (node != null && !string.IsNullOrEmpty(node.Value)) {
ts.TermStoreId = node.Value;
}
var node2 = doc.XPathSelectElement("//Name[text()='TermSetId']/../Value");
if (node2 != null && !string.IsNullOrEmpty(node2.Value)) {
ts.Id = node2.Value;
}
else {
continue; //No ID found
}
//Unique hites
if (!hashlist.Contains(ts.Id)) {
hashlist.Add(ts.Id);
termSets.Add(ts);
}
}
}
_termSets = termSets;
if (onlySpecificTermSetName != null) return (theChosenTermSet == null ? new List<TermSet>() : new List<TermSet>() { theChosenTermSet });
return termSets;
}
public static TermSet GetTermSetTerms(string site, string termName) {
var ts = GetAllTermSetNames(site, termName);
if (ts.Count == 0) throw new Exception("Could not find termset: " + termName);
var theTermSet = ts[0];
var proxy = new SharepointTaxWS.Taxonomywebservice();
proxy.UseDefaultCredentials = true;
proxy.PreAuthenticate = true;
proxy.Url = Path.Combine(site, "_vti_bin/taxonomyclientservice.asmx");
GetAuthCookie(proxy, site);
var lciden = 1033; //var lcidno = 1044; // System.Globalization.CultureInfo.CurrentCulture.LCID
var clientTime = DateTime.Now.AddYears(-2).ToUniversalTime().Ticks.ToString();
var termStoreId = new Guid(theTermSet.TermStoreId);// Guid.Parse(theTermSet.TermStoreId);
var termSetId = new Guid(theTermSet.Id);
string clientTimestamps = string.Format("<timeStamp>{0}</timeStamp>", clientTime);
string clientVersion = "<version>1</version>";
string termStoreIds = string.Format("<termStoreId>{0}</termStoreId>", termStoreId.ToString("D"));
string termSetIds = string.Format("<termSetId>{0}</termSetId>", termSetId.ToString("D"));
string serverTermSetTimestampXml;
string result = proxy.GetTermSets(termStoreIds, termSetIds, 1033, clientTimestamps, clientVersion, out serverTermSetTimestampXml);
var term = ParseTermSetInfo(result);
term.Description = theTermSet.Description;
term.Id = theTermSet.Id;
term.Name = theTermSet.Name;
return term;
}
//public static Term GetTermSetInfo(string site, string termName) {
// var proxy = new SharepointTaxWS.Taxonomywebservice();
// proxy.UseDefaultCredentials = true;
// proxy.PreAuthenticate = true;
// proxy.Url = Path.Combine(site, "_vti_bin/taxonomyclientservice.asmx");
// GetAuthCookie(proxy, site);
// var lciden = 1033; //var lcidno = 1044; // System.Globalization.CultureInfo.CurrentCulture.LCID
// var sets = proxy.GetChildTermsInTermSet(Guid.Parse(""), lciden, Guid.Parse("termsetguid"));
// var term = ParseTermInfo(sets);
// return term;
//}
public static Term GetTermInfo(string site, string termName) {
var proxy = new SharepointTaxWS.Taxonomywebservice();
proxy.UseDefaultCredentials = true;
proxy.PreAuthenticate = true;
proxy.Url = Path.Combine(site, "_vti_bin/taxonomyclientservice.asmx");
GetAuthCookie(proxy, site);
var lciden = 1033; //var lcidno = 1044; // System.Globalization.CultureInfo.CurrentCulture.LCID
var sets = proxy.GetTermsByLabel(termName, lciden, SharepointTaxWS.StringMatchOption.StartsWith, 100, null, false);
var term = ParseTermInfo(sets);
return term;
}
private static TermSet ParseTermSetInfo(string xml) {
//Not done
var info = XDocument.Parse(xml);
var ts = new TermSet();
ts.Terms = new List<Term>();
var n1 = info.XPathSelectElements("//T");
if (n1 != null) {
foreach (var item in n1) {
var t = new Term();
t.Id = item.Attribute("a9").Value;
t.Name = item.XPathSelectElement("LS/TL").Attribute("a32").Value;
t.TermSet = ts;
ts.Terms.Add(t);
}
}
return ts;
}
private static Term ParseTermInfo(string xml) {
var info = XDocument.Parse(xml);
var t = new Term();
var ts = new TermSet();
var n1 = info.XPathSelectElement("TermStore/T");
var n2 = info.XPathSelectElement("TermStore/T/LS/TL");
var n3 = info.XPathSelectElement("TermStore/T/TMS/TM");
if (n1 != null && n1.Attribute("a9") != null) {
t.Id = n1.Attribute("a9").Value;
}
if (n2 != null && n2.Attribute("a32") != null) {
t.Name = n2.Attribute("a32").Value;
}
if (n3 != null && n3.Attribute("a24") != null) {
ts.Id = n3.Attribute("a24").Value;
}
if (n3 != null && n3.Attribute("a12") != null) {
ts.Name = n3.Attribute("a12").Value;
}
t.TermSet = ts;
return t;
}
private static CookieCollection _theAuth;
private static bool _bNoClaims;
static void GetAuthCookie(SoapHttpClientProtocol proxy, string site) {
return;
//if (_bNoClaims) {
// return; //Ingen claims.
//}
//// get the cookie collection - authentication workaround
//CookieCollection cook = null;
//try {
// if (_theAuth == null) {
// cook = ClaimClientContext.GetAuthenticatedCookies(site, 925, 525);
// }
// else {
// cook = _theAuth;
// }
// _theAuth = cook;
// _bNoClaims = false;
//}
//catch (ApplicationException ex) {
// if (ex.Message.Contains("claim")) _bNoClaims = true;
// Console.Write("Auth feilet: " + ex.Message + " - ");
// //IGNORE
//}
//if (_theAuth != null) {
// proxy.CookieContainer = new CookieContainer();
// proxy.CookieContainer.Add(_theAuth);
//}
}
static void ctx_MixedAuthRequest(object sender, WebRequestEventArgs e) {
//add the header that tells SharePoint to use Windows Auth
e.WebRequestExecutor.RequestHeaders.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f");
}
}
public class TermSet {
public string Id { get; set; }
public string Name { get; set; }
public List<Term> Terms { get; set; }
public string TermStoreId { get; set; }
public string Description { get; set; }
public override string ToString() {
int tc = 0;
if (Terms != null) tc = Terms.Count;
return Name + "|" + Id + " (" + tc + "terms)";
}
}
public class Term {
public string Id { get; set; }
public string Name { get; set; }
public TermSet TermSet { get; set; }
public override string ToString() {
return Name + "|" + Id;
}
}
}