Only return specific properties - c#

I have developed my first API controlled in MVC4 and through the scaffolding I have got it to automatically output a list of items:
// GET api/ItemList
public IEnumerable<ItemOption> GetItemOptions()
{
var itemoptions = db.ItemOptions.Include(i => i.Item);
return itemoptions.AsEnumerable();
}
This shows all the item properties from my model:
public class ItemOption
{
public int ItemOptionId { get; set; }
public bool Active { get; set; }
public string Name { get; set; }
public string test1 { get; set; }
public double PriceNet { get; set; }
}
How can I specify specific fields I wish to be returned? For example, I just want the ItemOptionId, Active and Name to be returned.
I have tried adding additional includes, but this seems to be at an object level.

Try creating a new type to represent the properties you'd like to return:
public class ItemOptionResult
{
public int ItemOptionId { get; set; }
public bool Active { get; set; }
public string Name { get; set; }
}
And then projecting your ItemOption collection, like this:
// GET api/ItemList
public IEnumerable<ItemOptionResult> GetItemOptions()
{`enter code here`
var itemoptions =
db.ItemOptions
.Select(i =>
new ItemOptionResult
{
ItemOptionId = i.ItemOptionId,
Active = i.Active,
Name = i.Name
});
return itemoptions.AsEnumerable();
}

Try this :
var itemoptions = db.ItemOptions.Select(io => new ItemOption()
{
ItemOptionId = io.ItemOptionId,
Active = io.Active ,
Name = io.Name
}
return itemoptions.AsEnumerable();

Related

how can I preserve my class after list clear

I have 2 classes
public class Product
{
public DateTime Date { get; set; }
public string Name { get; set; }
public int Amount { get; set; }
}
public class Campaign
{
public long CampaignId { get; set; }
public string CampaignName { get; set; }
public List<Product> Products { get; set; }
}
Code:
var campaign = new Campaign();
campaign.CampaignId = Item.CampaignId;
campaign.CampaignId = Item.CampaignId;
campaign.CampaignName = Item.CampaignName;
campaign.Products = productList;
campaignList.Add(campaign);
productList.Clear();
When I call productList.Clear(), my "campaign" deletes its campaign.Products.
How can I prevent that from happening?
campaign.Products = new List<Product>(productList);
because campaign.Products is the same reference of productList
they are both pointing to the same list , any action on one will be reflected in the other varialbe
you need to clone (make another copy of the list) by different ways as follwoing
campaign.Products = productList.GetClone();
or
campaign.Products = productList.ToList();
or
campaign.Products.AddRange(productList);
check the following url
https://www.techiedelight.com/clone-list-in-csharp/

Loop through objects properties in an object

I have got an object like below
public class MainObj
{
public int BankDetailPercentage { get; set; }
public int PersonalDetailPercentage { get; set; }
public BankDetail BankDetail { get; set; }
public PersonalDetail PersonalDetail { get; set; }
}
public class BankDetail
{
public string Name { get; set; }
public string Branch { get; set; }
public string AccountNumber { get; set; }
}
public class PersonalDetail
{
public string Name { get; set; }
public string address { get; set; }
}
I need to loop through that MainObj Object and find how many properties of BankDetail and PersonalDetail objects are filled and on the basis of that I should set the percentage of filled properties in MainObj object's BankDetailPercentage and PersonalDetailPercentage fields and return it. How can I accomplish this, I have tried below but couldn't get how to do it
public MainObject calculatePercentage(MainObject mainObject)
{
int bdCount = 0, pdCount = 0, bdTotal = 3, pdTotal = 2;
PropertyInfo[] properties = typeof(MainObject).GetProperties();
foreach (var property in properties)
{
var value = property.GetValue(mainObject);
if (property.Name == "BankDetail")
{
//
}
}
return mainObject;
}
First you will need to get the instance of the object in question (which you have done in your code above.
var value = property.GetValue(mainObject);
Then you need to count how many properties are contained in that object. To do that we need to first get the properties.
var subProperties = property.PropertyType.GetProperties();
var propertyCount = subProperties.Length;
Now we need to check each of those properties to see if a value is set.
var populatedCount = 0;
foreach (var subProperty in subProperties)
{
if (!string.IsNullOrEmpty(subProperty.GetValue(value)))
{
populatedCount++;
}
}
Then take the percentage.
var percentage = (float)populatedCount / propertyCount;

How to manually map a List of object to a list of DTO?

I have these:
public class FamilyHead
{
public Guid HeadId { get; set; }
public string Name { get; set; }
}
public class Citizen
{
public Guid Id { get; set; }
public string Name { get; set; }
public short Age { get; set; }
// more properties
[ForeignKey("FamilyHead")]
public Guid HeadId { get; set; }
public virtual FamilyHead FamilyHead { get; set; }
}
public class CitizenDTO
{
public Guid Id { get; set; }
public string Name { get; set; }
public short Age { get; set; }
public Guid HeadId
public string HeadName { get; set; }
}
I can manually map it via extension method if it is a single instance:
public static CitizenDTO ToDTO(this Citizen citizen)
{
if (citizen == null) return null;
return new CitizenDTO {
Id = citizen.Id,
Name = citizen.Name,
HeadId = citizen.HeadId,
HeadName = citizen.FamilyHead.Name
}
}
var dto = aCitizen.ToDTO();
But how to map a list of citizens? I think Select() might do the work but I only know how to do it if the model and the dto have a same structure. Like this example:
IEnumerable<int> integers = new List<int>() { 1, 2, 3, 4, 5 };
IEnumerable<string> strings = integers.Select(i => i.ToString());
So how to map a list of it?
You can use Linq Select() as you used for string in your question, no need to write long extension method
IEnumerable<CitizenDTO> dto = citizens.Select(x => x.ToDTO());
I found the answer before finishing my question. Just iterate through the list and add mapped DTO to it. Silly me
// Extension method
public static IEnumerable<CitizenDTO> ToDTO(this IEnumerable<Citizen> citizens)
{
if (citizen == null) return null;
var dto = new List<CitizenDTO>();
foreach(var citizen in citizens) {
dto.Add(citizen.ToDTO());
}
return dto;
}
// How to use
IEnumerable<CitizenDTO> result = listOfCitizens.ToDTO();

Remove an object from a list based on an attribute of another list with linq

I have the following class to store objects from a REST API call from SharePoint:
[Serializable]
public class DocumentSearchResult
{
public string TotalCount { get; set; }
public string DocumentPath { get; set; }
public string DocumentTitle { get; set; }
public string DocumentSize { get; set; }
public string DocumentAuthor { get; set; }
public string DocumentDescription { get; set; }
public string DocumentFileExtension { get; set; }
public double DocumentRank { get; set; }
public Int64 DocumentDocId { get; set; }
public Int64 DocumentWorkId { get; set; }
public DateTime DocumentWrite { get; set; }
public string DocumentParentLink { get; set; }
public DateTime DocumentLastModifiedDate { get; set; }
public string DocumentFileType { get; set; }
//These next set of properties are used for Viewing the results in embedded or preview
public string DocumentRedirectedEmbededURL { get; set; }
public string DocumentRedirectPreviewURL { get; set; }
public string DocumentRedirectURL { get; set; }
}
I create a list of these objects in my code:
var docReturnResult = new List<DocumentSearchResult>();
I have another list I create using:
var filterList = this.Where(x => x.TenantId == TenantId);
this will return an IQueryable list that contains a value I need to filter the second list. The filterList has an attribute called SharePointId (x => x.SharePointId) that I need to use to filter the docReturnResult list. So I need to compare the filterList SharePointId to the docReturnResult DocumentDocId and remove any objects in the docReturnResult list that don't match the SharePointId's in the filterList.
This is what I tried last:
var trimResults = new DocumentSearchResult();
trimResults = docReturnResult.RemoveAll(x => x.DocumentDocId != filterList.Where(y => y.SharePointId));
but I get an error:
Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type.
Any help is much appreciated.
Try this, it should remove all documents from docReturnResult where match is not found in filterList
docReturnResult.RemoveAll(x => !filterList.Any(y => y.SharePointId == x.DocumentDocId));
Root cause of your error -
x.DocumentDocId != filterList.Where(y => y.SharePointId)
Right hand side will return IQuarable object and you are trying to compare it with DocumentDocId which will not work.
Edit
You don't need a new variable trmResults, as RemoveALL on docReturnResult will trim the same object, so you can just return docReturnResult
return docReturnResult.RemoveAll(x => !filterList.Any(y => y.SharePointId == x.DocumentDocId));

cannot be called with instance of type 'System.Data.Entity.Core.Objects.ObjectQuery

I want to Find Username by userId
this code snippet working
Discussion_CreateBy = db.AspNetUsers.Find(discussion.CreatedBy).UserName,
and this once not working in following controller class
Comment_CreateBy = db.AspNetUsers.Find(c.CreatedBy).UserName,
this is my model classes
public class DiscussionVM
{
public int Disussion_ID { get; set; }
public string Discussion_Title { get; set; }
public string Discussion_Description { get; set; }
public Nullable<System.DateTime> Discussion_CreateDate { get; set; }
public string Discussion_CreateBy { get; set; }
public string Comment_User { get; set; }
public IEnumerable<CommentVM> Comments { get; set; }
}
public class CommentVM
{
public int Comment_ID { get; set; }
public Nullable<System.DateTime> Comment_CreateDate { get; set; }
public string Comment_CreateBy { get; set; }
public string Comment_Description { get; set; }
}
this is whole controller class
public ActionResult Discussion_Preview()
{
int Discussion_ID = 1;
var discussion = db.AB_Discussion.Where(d => d.Discussion_ID == Discussion_ID).FirstOrDefault();
var comments = db.AB_DiscussionComments.Where(c => c.Discussion_ID == Discussion_ID);
DiscussionVM model = new DiscussionVM()
{
Disussion_ID = discussion.Discussion_ID,
Discussion_Title = discussion.Discussion_Name,
Discussion_Description = discussion.Discussion_Name,
Discussion_CreateBy = db.AspNetUsers.Find(discussion.CreatedBy).UserName,
Discussion_CreateDate = discussion.CreatedDate,
Comments = comments.Select(c => new CommentVM()
{
Comment_ID = c.Comment_ID,
Comment_Description = c.Comment_Discription,
Comment_CreateBy = db.AspNetUsers.Find(c.CreatedBy).UserName,
Comment_CreateDate = c.CreatedDate
})
};
return View(model);
}
Getting following error
Method 'Project.Models.AspNetUser Find(System.Object[])' declared on type 'System.Data.Entity.DbSet1[Project.Models.AspNetUser]' cannot be called with instance of type 'System.Data.Entity.Core.Objects.ObjectQuery1[Project.Models.AspNetUser]'
Discussion_CreateBy = db.AspNetUsers.Find(discussion.CreatedBy).UserName
Works because discussion is an in-memory object because you are executing a query by calling FirstOrDefault on it:
var discussion = db.AB_Discussion.Where(d => d.Discussion_ID == Discussion_ID).FirstOrDefault();
On the other hand in the following statement:
db.AspNetUsers.Find(c.CreatedBy).UserName
c is not queried yet because
db.AB_DiscussionComments.Where(c => c.Discussion_ID == Discussion_ID)
returns an IQueriable and not the actual collection of comments
The easiest way to fix it is to bring all your comments into memory (since you are anyway need them all) :
var comments = db.AB_DiscussionComments.Where(c => c.Discussion_ID == Discussion_ID).ToList();

Categories