C# - After executing the remove statement , list stays the same - c#

Everyone , I tried to remove item based on condition but it seems that after executing the remove statement my list stays the same .
class Menu
public class Menu : Entity
{
/// <summary>
/// Tạo mới guid khi gọi tới menu
/// </summary>
public Menu()
{
Random rnd = new Random();
Id = rnd.Next(1,999999) * DateTime.Now.Millisecond;
Guid = Guid.NewGuid();
}
/// <summary>
/// Danh sách Role
/// </summary>
[Required(ErrorMessage = nameof(EnumManageMenu.ENM01))]
public ICollection<string> Roles { get; set; }
/// <summary>
/// Danh sách Permisions
/// </summary>
[Required(ErrorMessage = nameof(EnumManageMenu.ENM02))]
public ICollection<string> Permisions { get; set; }
/// <summary>
/// Tên của từng menu
/// </summary>
[Required(ErrorMessage = nameof(EnumManageMenu.ENM03))]
[MaxLength(200, ErrorMessage = nameof(EnumManageMenu.ENM07))]
public string Name { get; set; }
/// <summary>
/// Đường dẫn
/// </summary>
[Required(ErrorMessage = nameof(EnumManageMenu.ENM09))]
[MaxLength(1000, ErrorMessage = nameof(EnumManageMenu.ENM08))]
public string Link { get; set; }
/// <summary>
/// Mỗi menu sẽ chứa một loại menu
/// </summary>
public ICollection<Menu> Items { get; set; }
/// <summary>
/// Mô tả thêm của từng menu
/// </summary>
[MaxLength(2000, ErrorMessage = nameof(EnumManageMenu.ENM11))]
public string Description { get; set; }
/// <summary>
/// Loại menu
/// </summary>
[Required(ErrorMessage = nameof(EnumManageMenu.ENM03))]
[MaxLength(1000, ErrorMessage = nameof(EnumManageMenu.ENM013))]
public string EnumCode { get; set; }
/// <summary>
/// Icon của menu
/// </summary>
[Required(ErrorMessage = nameof(EnumManageMenu.ENM016))]
[MaxLength(1000, ErrorMessage = nameof(EnumManageMenu.ENM017))]
public string Icon { get; set; }
/// <summary>
/// Trạng thái của menu
/// </summary>
public bool Active { get; set; }
/// <summary>
/// Sắp xếp danh sách menu
/// </summary>
public int SortOrder { get; set; }
}
below is my code
public async Task<MethodResult<List<MenuModel>>> GetAllMenuAsync()
{
MethodResult<List<MenuModel>> methodResult = new MethodResult<List<MenuModel>>();
List<Menu> empty = new List<Menu>();
List<Menu> menus = await _dbCollection.Find(FilterDefinition<Menu>.Empty).ToListAsync();
empty = menus;
int countList = menus.Count;
for (int i = 0; i < countList; i++)
{
foreach (var item in GetListNoDel(menus[i]))
{
if (item.IsDeleted)
{
empty.Remove(item);
}
}
}
List<MenuModel> menuModels = _mapper.Map<List<MenuModel>>(empty);
methodResult.Result = menuModels;
return methodResult;
}
private IEnumerable<Menu> GetListNoDel(Menu menus)
{
yield return menus;
foreach (var item in menus.Items)
{
foreach (var items in GetListNoDel(item))
{
yield return items;
}
}
}

You cannot "foreach" over a list and immediately remove items (as you undoubtedly know). So you will have to first find the items to remove, and then remove them. A twist in your case is that those "items to remove" can be at any depth in a menu tree.
So when you find an item to remove, also remember which list it appears in. Then you can directly remove it from that list.
void MainMethod()
{
var menulist = new List<Menu>(); // omitted: fill list
// get the *full* list of items to remove,
// so you don't change a list that is still used in a foreach
var todelete = ToDelete(menulist).ToList();
// and remove them from their parent list
foreach (var todo in todelete)
{
todo.list.Remove(todo.child);
}
}
private IEnumerable<(List<Menu> list, Menu child)> ToDelete(List<Menu> menuitems)
{
foreach (var item in menuitems)
{
if (item.IsDeleted)
{
// now we know that "item" must be removed from "menuitems"
yield return (menuitems, item);
}
else
{
// if the parent is deleted, then all children will be gone as well
// - so only recursively check non-deleted items
// pass the results of a recursive call up the call stack
foreach (var pairs in ToDelete(item.Items))
{
yield return pairs;
}
}
}
}

Related

Azure search document results is not binding to model

trying to use azure search documents and bind to a specific model
Model
/// <summary>
/// AzureSearchReturnModel
/// </summary>
public class AzureSearchReturnModel
{
/*// <summary>
/// Gets or sets the module identifier.
/// </summary>
/// <value>
/// The module identifier.
/// </value>
public int ModuleId { get; set; }*/
/// <summary>
/// Gets or sets the end item identifier.
/// </summary>
/// <value>
/// The end item identifier.
/// </value>
[SimpleField(IsFilterable = true)]
public int EndItemId { get; set; }
/*// <summary>
/// Gets or sets the end item type identifier.
/// </summary>
/// <value>
/// The end item type identifier.
/// </value>
public int EndItemTypeId { get; set; }
/// <summary>
/// Gets or sets the name of the file.
/// </summary>
/// <value>
/// The name of the file.
/// </value>
public string FileName { get; set; }
/// <summary>
/// Gets or sets the file extension.
/// </summary>
/// <value>
/// The file extension.
/// </value>
public string FileExtension { get; set; }
/// <summary>
/// Gets or sets the name of the module type.
/// </summary>
/// <value>
/// The name of the module type.
/// </value>
public string ModuleTypeName { get; set; }
/// <summary>
/// Gets or sets the size of the file.
/// </summary>
/// <value>
/// The size of the file.
/// </value>
public long FileSize { get; set; }*/
}
Here is a picture of my azure search settings on portal.azure for my index:
Here is the code I'm calling to obtain the results:
/// <summary>
/// Gets the files azure BLOB results from azure search.
/// </summary>
/// <param name="moduleId">The module identifier.</param>
/// <param name="endItemId">The end item identifier.</param>
/// <param name="endItemTypeId">The end item type identifier.</param>
/// <returns></returns>
public IEnumerable<FileManagerFileSystemItem> GetFilesAzureBlobResultsFromAzureSearch(int moduleId, int endItemId, int endItemTypeId)
{
SearchOptions options = new SearchOptions()
{
Filter = string.Format("endItemId eq '82'", endItemId),
/*Filter = string.Format("moduleId eq {0} and endItemId eq {1} and endItemTypeId eq {2}", moduleId.ToString(), endItemId.ToString(), endItemTypeId.ToString()),*/
};
SearchResults<AzureSearchReturnModel> results;
SearchClient searchClient = AzureKeyVaultUtilities.CreateSearchClientForQueries();
options.Select.Add("endItemId");
/*options.Select.Add("moduleId");
options.Select.Add("endItemId");
options.Select.Add("endItemTypeId");
options.Select.Add("moduleType");
options.Select.Add("fileName");
options.Select.Add("fileExtension");
options.Select.Add("metadata_storage_size");*/
results = searchClient.Search<AzureSearchReturnModel>("*", options);
return Enumerable.Empty<FileManagerFileSystemItem>();
}
The code runs without any issues, but my data is not binding to my model.
What am I doing wrong?
It appears the count is right? When I run the query via portal.azure.us it shows me 4 results:
Based on the info you provided, I created an index and write a demo for you.This is my index:
And my code below:
First I upload some docs and then query them with binding to a specific model as you want :
using System;
using Microsoft.Azure.Search;
using Microsoft.Azure.Search.Models;
namespace AzureSearchTest
{
class Program
{
static void Main(string[] args)
{
var searchServiceName = "";
var cred = "";
var indexName = "";
SearchServiceClient serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(cred));
ISearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName);
//UploadDocuments(indexClient);
var results = indexClient.Documents.Search<AzureSearchReturnModel>("*");
Console.WriteLine(results.Results.Count);
}
private static void UploadDocuments(ISearchIndexClient indexClient) {
var AzureSearchReturnModels = new AzureSearchReturnModel[] {
new AzureSearchReturnModel(){
ModuleId = "1" ,
EndItemId = "100",
EndItemTypeId = "200",
FileName= "test file 1",
FileExtension ="txt",
ModuleTypeName = "demo",
FileSize = 20000
},
new AzureSearchReturnModel(){
ModuleId = "2" ,
EndItemId = "100",
EndItemTypeId = "200",
FileName= "test file 2",
FileExtension ="aaa",
ModuleTypeName = "demo",
FileSize = 50000
},
new AzureSearchReturnModel(){
ModuleId = "3" ,
EndItemId = "100",
EndItemTypeId = "200",
FileName= "test file 3",
FileExtension ="bbb",
ModuleTypeName = "demo",
FileSize = 60000
}
};
var batch = IndexBatch.Upload(AzureSearchReturnModels);
indexClient.Documents.Index(batch);
}
}
public class AzureSearchReturnModel
{
[Newtonsoft.Json.JsonProperty(PropertyName = "moduleId")]
public String ModuleId { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "endItemId")]
public String EndItemId { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "endItemTypeId")]
public String EndItemTypeId { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "fileName")]
public string FileName { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "fileExtension")]
public string FileExtension { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "moduleType")]
public string ModuleTypeName { get; set; }
[Newtonsoft.Json.JsonProperty(PropertyName = "metadata_storage_size")]
public long FileSize { get; set; }
}
}
Result:

"About the "code" tag in the RichText field of "Contentful dotnet SDK

RichText in Contentful is deserialized to Document type, and Document is converted to MarkupString type for use. (I created an extension method).
When using the "code" tag in Contentful's RichTextEditor, the "pre" tag does not exist in the parent element, so line breaks and indentation are ignored by the browser.
Is there a way to add a parent element to any HTML tag?
public static MarkupString ToHtml(this Document doc)
{
var renderer = new HtmlRenderer();
var html = renderer.ToHtml(doc).GetAwaiter().GetResult();
return (MarkupString)html;
}
using Blazor ServerSide.
<div>
#entry.Content.ToHtml()
</div>
Model
public class ContentfulEntry
{
public SystemProperties Sys { get; set; }
public string Title { get; set; }
public Document Content { get; set; }
public string Description { get; set; }
public Asset Cover { get; set; }
}
Implement a custom renderer for Text:
public class CustomTextRenderer : IContentRenderer
{
/// <summary>
/// The order of this renderer in the collection.
/// </summary>
public int Order { get; set; } = 90;
/// <summary>
/// Whether or not this renderer supports the provided content.
/// </summary>
/// <param name="content">The content to evaluate.</param>
/// <returns>Returns true if the content is a textual node, otherwise false.</returns>
public bool SupportsContent(IContent content)
{
return content is Text;
}
/// <summary>
/// Renders the content to a string.
/// </summary>
/// <param name="content">The content to render.</param>
/// <returns>The content as a string.</returns>
public string Render(IContent content)
{
var text = content as Text;
var sb = new StringBuilder();
if (text.Marks != null)
{
foreach (var mark in text.Marks)
{
if(mark == "code">) {
sb.Append("<pre>");
}
sb.Append($"<{MarkToHtmlTag(mark)}>");
}
}
sb.Append(text.Value);
if (text.Marks != null)
{
foreach (var mark in text.Marks)
{
sb.Append($"</{MarkToHtmlTag(mark)}>");
if(mark == "code">) {
sb.Append("</pre>");
}
}
}
return sb.ToString();
}
private string MarkToHtmlTag(Mark mark)
{
switch (mark.Type)
{
case "bold":
return "strong";
case "underline":
return "u";
case "italic":
return "em";
case "code":
return "code";
}
return "span";
}
/// <summary>
/// Renders the content asynchronously.
/// </summary>
/// <param name="content">The content to render.</param>
/// <returns>The rendered string.</returns>
public Task<string> RenderAsync(IContent content)
{
return Task.FromResult(Render(content));
}
}
Then add it to your HTML renderers collection of renderers:
public static MarkupString ToHtml(this Document doc)
{
var renderer = new HtmlRenderer();
renderer.AddRenderer(new CustomTextRenderer());
var html = renderer.ToHtml(doc).GetAwaiter().GetResult();
return (MarkupString)html;
}
Note that the Order property controls the order in which renderers are evaluated. This means this custom renderer will be evaluated before the default ones.

Array types with <example> tag not working with Swagger (swashbuckle.aspnetcore)

I am using the summary and example tags for the swagger documentation.
I have a problem with the tag, it's not recognized by swagger when I use array :
I use swashbuckle.aspnetcore package Nuget.
Example :
[DataContract]
public class HeaderResponse
{
/// <summary>
/// Statut code
/// </summary>
///<example>400</example>
[DataMember]
public int StatusCode { get; set; }
/// <summary>
/// Title
/// </summary>
/// <example>Erreur sur methode1</example>
[DataMember]
public string Title { get; set; }
/// <summary>
/// List of errors
/// </summary>
///<example>["entry1", "entry2", "entry3"]</example>
[DataMember]
public List<string> ErrorList { get; } = new List<string>();
}
On swagger documentation, array is not interpreted :
I found others solutions by using ISchemaFilter like this :
public class SwaggerExcludeFilter : ISchemaFilter
{
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
switch (context.Type.Name)
{
case "HeaderResponse":
foreach (var property in schema.Properties)
{
if (property.Value.Type == "array")
{
var array = new OpenApiArray();
array.Add(new OpenApiString("item1"));
array.Add(new OpenApiString("item2"));
array.Add(new OpenApiString("item3"));
property.Value.Example = array;
}
}
break;
}
}
}
Is there no other way than to use ISchemaFilter to handle tags of type array?
You can try to do like this:
public List<string> ErrorList { get; } = new List<string>{"entry1", "entry2", "entry3"};
or:
[DataContract]
public class HeaderResponse
{
public HeaderResponse()
{
ErrorList = new List<string> {"entry1", "entry2", "entry3" };
}
/// <summary>
/// Statut code
/// </summary>
///<example>400</example>
[DataMember]
public int StatusCode { get; set; }
/// <summary>
/// Title
/// </summary>
/// <example>Erreur sur methode1</example>
[DataMember]
public string Title { get; set; }
/// <summary>
/// List of errors
/// </summary>
[DataMember]
public List<string> ErrorList { get; set; }
}
Here is a demo:
[HttpPost("TestPar")]
public IActionResult TestPar(HeaderResponse h)
{
return Json(h);
}
result:
The quotes must be escaped using "
/// <summary>
/// List of errors
/// </summary>
///<example>["entry1","entry2","entry3"]</example>
[DataMember]
public List<string> ErrorList { get; } = new List<string>();
I have the same problem and I try this. you can add a condition on the name of the property and add the null return in order not to lose the example on the other properties. But the best solution would be to be able to find a generic solution. How is it possible to get the example tag and the property name with ISchemaFilter ? This is my solution :
public void Apply(OpenApiSchema schema, SchemaFilterContext context)
{
schema.Example = GetExampleOrNullFor(schema, context);
}
private IOpenApiAny GetExampleOrNullFor(OpenApiSchema schema, SchemaFilterContext context)
{
switch (context.Type.Name)
{
case "MyClass":
foreach (var property in schema.Properties)
{
//Array property, which wraps its elements
if (property.Value.Type == "array")
{
if (property.Key == "MyProperty1")
{
var array = new OpenApiArray();
array.Add(new OpenApiString("item1"));
array.Add(new OpenApiString("item2"));
property.Value.Example = array;
}
else if (property.Key == "MyProperty2")
{
var array = new OpenApiArray();
array.Add(new OpenApiString("item1"));
property.Value.Example = array;
}
}
}
return null;
default:
return null;
}
}
Support for examples using XML comments on arrays was added in Swashbuckle.AspNetCore version 6.0.0.
It's mentioned in this GitHub issue and their documentation shows the following example:
/// <summary>
/// The sizes the product is available in
/// </summary>
/// <example>["Small", "Medium", "Large"]</example>
public List<string> Sizes { get; set; }

How would I set a model property to the result of an extension's method?

I have a data model consisting of a couple of properties and methods, this data model inherits from an interface. However, I've now created a static extension and would like to set one of my model properties to the result of that extension method.
These are my models and extensions:
PublishedContentModel:
namespace CMS.Core.Models
{
public class PublishedContentModel : IPublishedContent
{
/// <summary>
/// The id of this node.
/// </summary>
public Int32 Id { get; set; }
/// <summary>
/// The name of this node.
/// </summary>
public String Name { get; set; }
/// <summary>
/// The url path.
/// </summary>
public String Path { get; set; }
/// <summary>
/// This nodes document id.
/// </summary>
public Int32 DocumentId { get; set; }
/// <summary>
/// The parent node's id.
/// </summary>
public IPublishedContent Parent { get; set; }
/// <summary>
/// The collection of this node's children.
/// </summary>
public IEnumerable<IPublishedContent> Children { get; set; }
/// <summary>
/// The collection of ancestors.
/// </summary>
public IEnumerable<IPublishedContent> Ancestors ()
{
IEnumerable<IPublishedContent> colContentNodes = ContentService.GetAllContentNodes();
List<IPublishedContent> colAncestors = new List<IPublishedContent>();
foreach (IPublishedContent objContentNode in colContentNodes.Where(x => x.Descendants().Any(y => y.Id == Id)))
{
colAncestors.Add(objContentNode);
}
return colAncestors;
}
/// <summary>
/// The collection of all nodes under this.
/// </summary>
public IEnumerable<IPublishedContent> Descendants ()
{
// - Get the children and create a collection for descendants.
IEnumerable<IPublishedContent> colChildren = Children;
List<IPublishedContent> colDescendants = new List<IPublishedContent>();
if (colChildren.Any())
{
colDescendants = colChildren.ToList();
foreach (IPublishedContent objChild in colChildren)
{
IEnumerable<IPublishedContent> colChildsChildren = objChild.Children;
// - Check if this node has children.
if (colChildsChildren.Any())
{
colDescendants.AddRange(colChildsChildren);
}
}
}
return colDescendants;
}
}
}
ContentModelExtensions:
namespace CMS.Core.Models
{
public static class ContentModelExtensions
{
public static IEnumerable<IPublishedContent> Children (this IPublishedContent Content)
{
IEnumerable<IPublishedContent> colContentNodes = ContentService.GetAllContentNodes();
List<IPublishedContent> colChildren = new List<IPublishedContent>();
foreach (IPublishedContent objContentNode in colContentNodes.Where(x => x.Parent != null))
{
colChildren.Add(objContentNode);
}
return colChildren;
}
public static IEnumerable<T> Children<T> (this IPublishedContent Content) where T : class, IPublishedContent
{
IEnumerable<IPublishedContent> colContentNodes = ContentService.GetAllContentNodes();
List<T> colChildren = new List<T>();
foreach (T objContentNode in colContentNodes.Where(x => x.Parent != null))
{
colChildren.Add(objContentNode);
}
return colChildren;
}
}
}
The issue with this code is that I can't do Children.Any() seeing as the IEnumerable for this is null. I tried fixing this by setting the Children property when it gets sent to the view, like this:
objContentNode = new PublishedContentModel ()
{
Id = Convert.ToInt32(objReader["Id"]),
Name = Convert.ToString(objReader["Name"]),
Parent = GetContentNodeById(Convert.ToInt32(objReader["ParentId"])),
Path = Convert.ToString(objReader["Path"]),
DocumentId = Convert.ToInt32(objReader["DocumentId"]),
Children = ContentModelExtensions.Children(objContentNode)
};
Put that just makes the connection timeout, any help would be appreciated. Let me know if I haven't explained my issue well enough.
TLDR:
I want to set public IEnumerable<IPublishedContent> Children { get; set; } to the result of ContentModelExtensions.Children()

How to add item into a list which is inside another list. and use condition to find the another list

namespace Winning.FrameWork.PageMenuSetting
{
public static class PreviewMenuHelper
{
/// <summary>
/// 预览数据返回类型
/// </summary>
public class TagPageInfo
{
public string TabPageName { get; set; }
public List<MenuGroupInfo> ListMenuGroups { get; set; }
}
/// <summary>
/// menugroup 返回类型
/// </summary>
public class MenuGroupInfo
{
public string GroupId{ get; set; }
public string GroupName{ get; set; }
public List<MenuItemInfo> MenuItems{ get; set; }
}
/// <summary>
/// menuitem 返回类型
/// </summary>
public class MenuItemInfo
{
public string CommandId { get; set; }
public string AliasName { get; set; }
public string ICON { get; set; }
public int ShowMode { get; set; }
public int ShowIndex { get; set; }
}
/// <summary>
/// 获得所有的指定pageid的menu
/// </summary>
public static List<TagPageInfo> GetPageMenuInfo(string pageid)
{
List<TagPageInfo> listPage = new List<TagPageInfo>();
TagPageInfo tagPageInfo = new TagPageInfo();
listPage.Add(tagPageInfo);
listPage[0].TabPageName = pageid.Trim();
MenuGroupInfo menuGroupInfo = new MenuGroupInfo();
MenuItemInfo menuItemInfo = new MenuItemInfo();
int groupid = 1 ;
var MenuItemsInfos = DataHelper.DataObj.QueryTable<PUB_MENU_ITEMINFO>(SystemType.H0, p => p.PAGEID.Trim() == pageid.Trim());
listPage[0].ListMenuGroups = new List<MenuGroupInfo>();
foreach (PUB_MENU_ITEMINFO item in MenuItemsInfos)
{
if (listPage[0].ListMenuGroups.Count<=0|| listPage[0].ListMenuGroups.FirstOrDefault(p => p.GroupName == item.MEMO) == null)
{
menuGroupInfo.GroupId = groupid.ToString();
menuGroupInfo.GroupName = item.MEMO;
menuItemInfo.CommandId = item.COMMANDID;
menuItemInfo.AliasName = item.MENUITEMNAME;
menuItemInfo.ICON = item.ICON;
menuItemInfo.ShowMode = 0;
menuItemInfo.ShowIndex = 1;
menuGroupInfo.MenuItems = new List<MenuItemInfo>();
menuGroupInfo.MenuItems.Add(menuItemInfo);
listPage[0].ListMenuGroups = new List<MenuGroupInfo>();
listPage[0].ListMenuGroups.Add(menuGroupInfo);
groupid++;
}
else
{
//var existgroup = listPage[0].ListMenuGroups.FirstOrDefault(t => t.GroupName == item.MEMO) as MenuGroupInfo;
menuItemInfo.AliasName=item.MENUITEMNAME;
menuItemInfo.CommandId=item.COMMANDID;
menuItemInfo.ShowMode = 0;
menuItemInfo.ShowIndex = 1;
//this is where the problem is. all items inside the list<menuiteminfo> become the same as the last menuiteminfo i insert into.
((listPage[0].ListMenuGroups.FirstOrDefault(t => t.GroupName == item.MEMO) as MenuGroupInfo).MenuItems as List<MenuItemInfo>).Add(menuItemInfo);
}
}
return listPage;
}
}
}
Could not insert new menuiteminfo into the one exist menugroupinfo.
All the menuiteminfo become the last item I insert into, don't know why! Please mainly check the several last line to point where I go wrong!
MenuGroupInfo menuGroupInfo = new MenuGroupInfo();
MenuItemInfo menuItemInfo = new MenuItemInfo();
problem solved, i defined a globle viriable. so all the new MenuItemInfo are add into the single MenuGroupInfo.

Categories

Resources