Null Object Pattern with repository pattern and unit of work - asp.net-mvc

I am using a unit of work to retrieve records / record form database, i am trying to implement some kind of a null object design pattern so that i dont have to check every-time if the returned object is null or not. I have tried searching online however i have not land on any good explanation on how to best achieve this in this current situation, I am familiar with the traditional approach for Null Object Design Pattern where you create a copy null class with hard coded properties and methods and return either the class or null-class based on outcome of the search in Db. however I feel that with the unit of work and repository patterns this approach is not valid. here is the class.
public class HR_Setup_Location
{
public string Street1 { get; set; }
public string Street2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Country { get; set; }
public string FullAddress{
get { return $"{Street1} {City} {Country}"; }
}
[ForeignKey("Setup")]
public int SetupId { get; set; }
public virtual Setup Setup { get; set; }
public virtual ICollection<HR_Setup_OfficeEvent> HR_Setup_OfficeEvents { get; set; }
}
I tried the following , which is doing the job for now, however i appreciate your feedback on the approach if you have tried something similar in a similar situation. and what is the best way to address null objects in this pattern.
public interface ISetupLocationRepository : IRepository<HR_Setup_Location>
{
HR_Setup_Location GetById(int LocationId);
}
public class SetupLocationRepository : Repository<HR_Setup_Location>, ISetupLocationRepository
{
private readonly DataBaseContext context;
public SetupLocationRepository(DataBaseContext context)
: base(context)
{
this.context = context;
}
public HR_Setup_Location GetById(int LocationId)
{
HR_Setup_Location Obj = context.HR_Setup_Locations.Where(p => p.HR_Setup_LocationId == LocationId).FirstOrDefault();
if (Obj != null)
{
return Obj;
}
else
{
HR_Setup_Location Obj2 = new HR_Setup_Location()
{
HR_Setup_LocationId = -1,
Street1 = string.Empty,
Street2 = string.Empty,
City = string.Empty,
State = string.Empty,
Country = string.Empty,
SetupId = -1,
};
Obj2.HR_Setup_OfficeEvents = null;
return Obj2;
}
}
}
Then with the unit of work I am trying to access the location address by calling:
string LocationName = Vacancy.HR_Setup_LocationId.HasValue ? unitOfWork.SetupLocations.GetById(Vacancy.HR_Setup_LocationId.Value).FullAddress : "";
so basically if no id is based it will return an empty string, and if an id is passed but the record is no longer available in DataBase then the null object return empty for Fulladdress

Related

The entity type <type> is not part of the model from the current context

I get this error (An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code
The entity type tblMessage is not part of the model for the current context.) and have tried fixes I found online but they didnt seem to help. I also did somethin similar for another database tabel earlier in the code.
Im trying to retrieve messages form my database table called tblMessages.
Constructor:
public JsonResult ConversationWithContact(int contact)
{
if (Session["UserID"] == null)
{
return Json(new {status = "error", message = "User is not logged in"});
}
//var currentUser = (Models.tblUser)Session["UserID"];
var conversations = new List<Models.tblMessage>();
using (var db = new Models.ChatContext())
{
int currentUserId = (int)Session["UserID"];
var currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
conversations = db.Conversations.Where(c => (c.receiverId == currentUser.Id
&& c.senderId == contact) ||
(c.receiverId == contact
&& c.senderId == currentUser.Id))
.OrderBy(c => c.created_at)
.ToList();
}
return Json(
new {status = "success", data = conversations},
JsonRequestBehavior.AllowGet
);
}
Context:
public ChatContext() : base("TrinityEntities")
{
}
public static ChatContext Create()
{
return new ChatContext();
}
public DbSet<tblUser> Users { get; set; }
public DbSet<tblMessage> Conversations { get; set; }
Database model class:
public class tblMessage
{
public tblMessage()
{
status = messageStatus.Sent;
}
public enum messageStatus
{
Sent,
Delivered
}
public int Id { get; set; }
public int senderId { get; set; }
public int receiverId { get; set; }
public string message { get; set; }
public messageStatus status { get; set; }
public System.DateTime created_at { get; set; }
}
Here is issue with Table Mapping to database. each entity will be set up to map to a table with the same name as the DbSet<TEntity> property that exposes to the derived context. If no DbSet<TEntity> is included for the given entity, the class name is used.
as you set in your code Users and Conversations is not table name. for that you can customize also refere https://learn.microsoft.com/en-us/ef/core/modeling/relational/tables
and use Data Annotations for specify table name.
public messageStatus status { get; set; }
i think this property is not not part of your table column so you have to specify [NotMapped] Data Annotations.
after changes and adding Data Annotations to table context and table look likes.
public class ChatContext : DbContext
{
public ChatContext()
{
}
public virtual DbSet<tblUser> Users { get; set; }
public virtual DbSet<tblMessage> Conversations { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=test;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
}
and your models(tables) entities look like.
[Table("tblMessage")]
public class tblMessage
{
public tblMessage()
{
status = messageStatus.Sent;
}
public enum messageStatus
{
Sent,
Delivered
}
public int Id { get; set; }
public int senderId { get; set; }
public int receiverId { get; set; }
public string message { get; set; }
[NotMapped]
public messageStatus status { get; set; }
public System.DateTime created_at { get; set; }
}
[Table("tblUser")]
public class tblUser
{
public int id { get; set; }
public string name { get; set; }
}
now you can access your Conversations and Users after adding [Table("<table-name>")] Data-Annotations.
also you can use Fluent API for table mapping.
after using table mapping table after debug code image like.
i hope it helps you and let me know if require any more information. :)

How Can I Use Custom Validation Attributes on Child Models of a DB Entity?

Summary:
I want a data annotation validator to reference another property in the same class (TitleAuthorAndPublishingConfiguration).
However, DB.SaveChanges() is not being called on this class directly. Rather it is being called on the parent of this class (WebsiteConfiguration).
Therefore validationContext.ObjectType is returning WebsiteConfiguration and I am unable to refer to properties of TitleAuthorAndPublishingConfiguration within the data annotation validator.
WebsiteConfiguration.cs
public class WebsiteConfiguration
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; }
public TitleAuthorAndPublishingConfiguration TitleAuthorAndPublishing { get; set; }
public BookChaptersAndSectionsConfiguration BookChaptersAndSections { get; set; }
public SocialMediaLoginsConfiguration SocialMediaLogins { get; set; }
public TagGroupsConfiguration TagGroups { get; set; }
}
public class TitleAuthorAndPublishingConfiguration
{
public string BookTitle { get; set; }
public bool IsPublished { get; set; }
// how do I access a property of current model when calling DB.SaveChanges() on parent?
[RequiredIfOtherFieldIsEnabled("IsPublished")]
public string Publisher { get; set; }
}
// ... and other sub models...
ApplicationDbContext.cs
DbSet<WebsiteConfiguration> WebsiteConfiguration {get;set;}
Example Update Code
public void SeedWebsiteConfiguration()
{
var titleAuthorAndPublishingConfiguration = new TitleAuthorAndPublishingConfiguration()
{
// seed values
};
var bookChaptersAndSectionsConfiguration = new BookChaptersAndSectionsConfiguration()
{
// seed values
};
var socialMediaLoginConfiguration = new SocialMediaLoginsConfiguration()
{
// seed values
};
var tagGroupsConfiguration = new TagGroupsConfiguration()
{
// seed values
};
var websiteConfiguration = new WebsiteConfiguration()
{
TitleAuthorAndPublishing = titleAuthorAndPublishingConfiguration,
BookChaptersAndSections = bookChaptersAndSectionsConfiguration,
SocialMediaLogins = socialMediaLoginConfiguration,
TagGroups = tagGroupsConfiguration
};
DB.WebsiteConfiguration.Add(websiteConfiguration);
DB.SaveChanges();
}
Validator Code
public class RequiredIfOtherFieldIsEnabledAttribute : ValidationAttribute
{
private string _ifWhatIsEnabled { get; set; }
public RequiredIfOtherFieldIsEnabledAttribute(string IfWhatIsEnabled)
{
_ifWhatIsEnabled = IfWhatIsEnabled;
}
protected override ValidationResult IsValid(object currentPropertyValue, ValidationContext validationContext)
{
var isEnabledProperty = validationContext.ObjectType.GetProperty(_ifWhatIsEnabled);
if (isEnabledProperty == null)
{
return new ValidationResult(
string.Format("Unknown property: {0}", _ifWhatIsEnabled)
);
}
var isEnabledPropertyValue = (bool)isEnabledProperty.GetValue(validationContext.ObjectInstance, null);
if (isEnabledPropertyValue == true)
{
if (String.IsNullOrEmpty(currentPropertyValue.ToString()))
{
return new ValidationResult(String.Format("This field is required if {0} is enabled", isEnabledProperty));
}
}
return ValidationResult.Success;
}
}
Questions
Is there a way for me to access child model properties from validationContext?
Am I misguided in my approach? Is there a better way to store multiple models as part of a larger model in a single DB table?
I was hoping not to have multiple config tables and calls to the DB. (There are 4 child models in this example, but there may be 10+ in the next app.)
The setup above meets my needs in so many ways. But I don't want to give up the functionality of DataAnnotations on the sub models!
Bonus Question
I have come across a few posts like this one:
How can I tell the Data Annotations validator to also validate complex child properties?
But that is 4 years old, and I'm wondering if anything has changed since then.
Am I trying to do something that is basically impossible (or at least very difficult)?
Am I trying to do something that is basically impossible (or at least
very difficult)?
No, there is a very simple solution that integrates perfectly with the framework and technologies using DataAnnotations.
You can create a custom ValidationAttribute that is called by EF Validation and call Validator.TryValidateObject inside. This way, when CustomValidation.IsValid is called by EF you launch child complex object validation by hand and so on for the whole object graph. As a bonus, you can gather all errors thanks to CompositeValidationResult.
i.e.
using System;
using System.ComponentModel.DataAnnotations;
using System.Collections.Generic;
public class Program
{
public static void Main() {
var person = new Person {
Address = new Address {
City = "SmallVille",
State = "TX",
Zip = new ZipCode()
},
Name = "Kent"
};
var context = new ValidationContext(person, null, null);
var results = new List<ValidationResult>();
Validator.TryValidateObject(person, context, results, true);
PrintResults(results, 0);
Console.ReadKey();
}
private static void PrintResults(IEnumerable<ValidationResult> results, Int32 indentationLevel) {
foreach (var validationResult in results) {
Console.WriteLine(validationResult.ErrorMessage);
Console.WriteLine();
if (validationResult is CompositeValidationResult) {
PrintResults(((CompositeValidationResult)validationResult).Results, indentationLevel + 1);
}
}
}
}
public class ValidateObjectAttribute: ValidationAttribute {
protected override ValidationResult IsValid(object value, ValidationContext validationContext) {
var results = new List<ValidationResult>();
var context = new ValidationContext(value, null, null);
Validator.TryValidateObject(value, context, results, true);
if (results.Count != 0) {
var compositeResults = new CompositeValidationResult(String.Format("Validation for {0} failed!", validationContext.DisplayName));
results.ForEach(compositeResults.AddResult);
return compositeResults;
}
return ValidationResult.Success;
}
}
public class CompositeValidationResult: ValidationResult {
private readonly List<ValidationResult> _results = new List<ValidationResult>();
public IEnumerable<ValidationResult> Results {
get {
return _results;
}
}
public CompositeValidationResult(string errorMessage) : base(errorMessage) {}
public CompositeValidationResult(string errorMessage, IEnumerable<string> memberNames) : base(errorMessage, memberNames) {}
protected CompositeValidationResult(ValidationResult validationResult) : base(validationResult) {}
public void AddResult(ValidationResult validationResult) {
_results.Add(validationResult);
}
}
public class Person {
[Required]
public String Name { get; set; }
[Required, ValidateObject]
public Address Address { get; set; }
}
public class Address {
[Required]
public String Street1 { get; set; }
public String Street2 { get; set; }
[Required]
public String City { get; set; }
[Required]
public String State { get; set; }
[Required, ValidateObject]
public ZipCode Zip { get; set; }
}
public class ZipCode {
[Required]
public String PrimaryCode { get; set; }
public String SubCode { get; set; }
}

Nhibernate Domain Ojbect/View Model Mapping (One-to-Many)

Assume this simple Domain in my core assembly:
public class Country
{
protected ICollection<Province> _provinces = null;
public virtual int Id { get; protected set; }
public virtual string Name { get; set; }
public virtual string IsoCode2 { get; set; }
public virtual string IsoCode3 { get; set; }
public virtual int IsoCodeNumeric { get; set; }
public virtual ICollection<Province> Provinces
{
get { return _provinces ?? (_provinces = new List<Province>()); }
set { _provinces = value; }
}
}
public class Province
{
public virtual int Id { get; protected set; }
public virtual Country Country { get; set; }
public virtual string Name { get; set; }
public virtual string Abbreviation { get; set; }
}
The view models in my presentation layer are almost the same:
public class CountryModel
{
public int Id { get; set; }
public string Name { get; set; }
public string IsoCode2 { get; set; }
public string IsoCode3 { get; set; }
public int IsoCodeNumeric { get; set; }
public int NumberOfProvinces { get; set; }
}
public class ProvinceModel
{
public int Id { get; set; }
public int CountryId { get; set; }
public string Name { get; set; }
public string Abbreviation { get; set; }
}
I am creating some Extension methods for mapping back and forth between domain objects/view models:
public static class Extensions
{
public static Country ToEntity(this CountryModel model, Country entity = null)
{
if (entity == null)
entity = new Country();
entity.Name = model.Name;
entity.IsoCode2 = model.IsoCode2;
entity.IsoCode3 = model.IsoCode3;
entity.IsoCodeNumeric = model.IsoCodeNumeric;
entity.AddressFormat = model.AddressFormat;
entity.CanBillTo = model.CanBillTo;
entity.CanShipTo = model.CanShipTo;
entity.IsPublished = model.IsPublished;
return entity;
}
public static CountryModel ToModel(this Country entity, bool includeProvinceCount = false, CountryModel model = null)
{
if (model == null)
model = new CountryModel();
model.Id = entity.Id;
model.Name = entity.Name;
model.IsoCode2 = entity.IsoCode2;
model.IsoCode3 = entity.IsoCode3;
model.IsoCodeNumeric = entity.IsoCodeNumeric;
model.AddressFormat = entity.AddressFormat;
model.CanBillTo = entity.CanBillTo;
model.CanShipTo = entity.CanShipTo;
model.IsPublished = entity.IsPublished;
if (includeProvinceCount)
model.NumberOfProvinces = entity.Provinces.Count;
return model;
}
public static Province ToEntity(this ProvinceModel model, Province entity = null)
{
if (entity == null)
entity = new Province();
//entity.Country = LoadCountryById(model.CountryId); ???? <-- HERE
entity.Name = model.Name;
entity.Abbreviation = model.Abbreviation;
entity.CanBillTo = model.CanBillTo;
entity.CanShipTo = model.CanShipTo;
entity.IsPublished = model.IsPublished;
return entity;
}
public static ProvinceModel ToModel(this Province entity, ProvinceModel model)
{
if (model == null)
model = new ProvinceModel();
model.Id = entity.Id;
model.CountryId = entity.Country.Id;
model.Name = entity.Name;
model.Abbreviation = entity.Abbreviation;
model.CanBillTo = entity.CanBillTo;
model.CanShipTo = entity.CanShipTo;
model.IsPublished = entity.IsPublished;
return model;
}
}
With Entity Framework, the Province domain object would have had both Country and the corresponding CountryId properties. I could assign the Country by simply setting the CountryId.
With NHibernate, the id of the foreign key is unnecessary when creating the domain. So how do you map the ProvinceModel CountryId back to a Country object?
I've gone through all kinds of steps to abstract things into interfaces and use Dependency Injection. Should I use a service locator from within the mapping extensions and look it up? Should I look up the country outside of the mapping extension and require it as a parameter on the extension method? What are the recommended ways of handing this scenario?
Second, with NHibernate they recommend adding helper functions to the domain objects in order to maintain associations (not positive, but I think EF handles this "automagically" for me). For example, I would add a SetCountry method on Province, and AddProvince and RemoveProvince methods on Country.
Doesn't this hurt performance? Instead of simply setting the Country for a Province (which is where the association is managed), the entire list of the new Country's Provinces are loaded to see if it is already in the list before adding to the collection, then the entire list of the old Country's Provinces are loaded to see if the province needs to be removed from the collection.
[in EF] I could assign the Country by simply setting the CountryId.
This isn't true and in my opinion this is a major defect with Entity Framework. Having both Country and CountryId properties is a hack that allows you to set the Country without retrieving it from the database by setting the CountryId. In a web app this works because the record is saved with the CountryId foreign key set so the next time you load it the Country is populated. NHibernate's solution to this pattern is the ISession.Load method that creates a dynamic proxy.
In your example you would do something like
province.Country = session.Load<Country>(provinceModel.CountryId);
As to your second question, in general I only use methods to encapsulate access to collections. This ensures that the collection itself is not replaced by a setter and allows me to maintain both sides of the relationship. I would model this as:
public class Country
{
private ICollection<Province> _provinces;
public Country()
{
_provinces = new HashSet<Province>();
}
public virtual IEnumerable<Province> Provinces
{
get { return _provinces; }
}
public virtual void AddProvince(Province province)
{
province.Country = this;
_provinces.Add(province);
}
public virtual void RemoveProvince(Province province)
{
province.Country = null;
_provinces.Remove(province);
}
}
As you noted, this does require loading the collection. You have to remember that NHibernate (and Hibernate) were originally designed for stateful applications and many of the usage patterns are not strictly necessary in stateless web applications. However, I would profile performance before deviating from some of these patterns. For example, you may want to validate your objects before committing them and that requires that the in-memory representations are consistent.

Partial Updates for Entities with Repository/DTO patterns in MVC (prepping for API)

I've built my Domain model layer, my repository layer, and now I'm working on my DTO layer to be used by a webApi project. I'm in the middle of implementing an Update service method, and I'm wondering about partial updates. Here's my DTO class:
public class FullPersonDto
{
public FullPersonDto()
{
Friends = new List<Person>();
}
public FullPersonDto(Person person)
{
PersonId = person.PersonId;
DateCreated = person.DateCreated;
Details = person.Details;
Friends = new List<Person>();
foreach (Person friend in person.Friends)
{
Friends.Add(new PersonDto(friend));
}
}
[Key]
public int PersonId { get; set; }
[Required]
public virtual DateTime DateCreated { get; set; }
public virtual string Details { get; set; }
public List<Person> Friends { get; set; }
public Person ToEntity()
{
var person = new Person
{
PersonId = PersonId,
DateCreated = (DateTime) DateCreated,
Details = Details,
Friends = new List<Person>()
};
foreach (PersonDto friend in Friends)
{
person.Friends.Add(friend.ToEntity());
}
return person;
}
}
Here's my Update method in my Repository:
public Person UpdatePerson(Person person)
{
var entry = _db.Entry(person);
if (entry.State == EntityState.Detached)
{
var dbSet = _db.Set<Person>();
Person attachedPerson = dbSet.Find(person.PersonId);
if (attachedPerson != null)
{
var attachedEntry = _db.Entry(attachedPerson);
attachedEntry.CurrentValues.SetValues(person); // what if values are null, like ID, or DateCreated?
}
else
{
entry.State = EntityState.Modified;
}
}
SaveChanges();
return person;
}
My question is: What if I only need to update the Details of a person via my webAPI? Is the convention to construct an entire PersonDto and Update the entire object using SetValues, or is there any way I can specify that I only want a single field updated so that I don't have to send a ton of data over the wire (that I don't really need)?
If it is possible to do partial updates, when is it ever good to update the entire entity? Even if I have to update 5/7 properties, it requires that I send old data for 2/7 to re-write so that SetValues doesn't write nulls into my fields from my DTO.
Any help here would be awesome... totally new to this stuff and trying to learn everything right. Thank you.
I've taken similar approach to do optimization, and I've faced same issues with null values when attaching (not just null, you'll have issue with boolean as well). This is what I've come up with:
public static void Update<T>(this DbContext context, IDTO dto)
where T : class, IEntity
{
T TEntity = context.Set<T>().Local.FirstOrDefault(x => x.Id == dto.Id);
if (TEntity == null)
{
TEntity = context.Set<T>().Create();
TEntity.Id = dto.Id;
context.Set<T>().Attach(TEntity);
}
context.Entry(TEntity).CurrentValues.SetValues(dto);
var attribute = dto.GetAttribute<EnsureUpdatedAttribute>();
if (attribute != null)
{
foreach (var property in attribute.Properties)
context.Entry(TEntity).Property(property).IsModified = true;
}
}
That is extension method for DbContext. Here are the interfaces IDTO and IEntity:
public interface IDTO
{
int Id { get; set; }
}
public interface IEntity
{
int Id { get; set; }
Nullable<DateTime> Modified { get; set; }
Nullable<DateTime> Created { get; set; }
}
I'm using my custom EnsureUpdatedAttribute to annotate what properties should always be updated (to deal with nulls / default values not being tracked):
public class EnsureUpdatedAttribute : Attribute
{
public IEnumerable<string> Properties { get; private set; }
public EnsureUpdatedAttribute(params string[] properties)
{
Properties = properties.AsEnumerable();
}
}
And this is a sample of usage:
public class Sample : IEntity
{
public int Id { get; set; }
public string Name { get; set; }
public bool Active { get; set; }
public Nullable<DateTime> Modified { get; set; }
public Nullable<DateTime> Created { get; set; }
}
[EnsureUpdated("Active")] /// requirement for entity framework change tracking, read about stub entities
public class SampleDTO : IDTO
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[JsonIgnore] /// How to exclude property from going on the wire / ignored for serialization
public bool Active { get; set; }
}
[HttpPost]
public HttpResponseMessage SaveSample(SampleDTO dto)
{
dto.Active = true;
_ctx.AddModel<Sample>(dto);
_ctx.SaveChanges();
return NoContent();
}
return NoContent() is just extension for returning 204 (NoContent).
Hope this helps.
Theres a few options you have, you can create a stored procedure to update the required parts (I wouldnt do this), or you can manually select the fileds to update on the model before saving the context changes with EF.
Heres an example how to update a specific field:
public void UpdatePerson(int personId, string details)
{
var person = new Person() { Id = personId, Details = details };
db.Persons.Attach(personId);
db.Entry(person).Property(x => x.Details).IsModified = true;
db.SaveChanges();
}
It will depend on your scenario what you want to do, but generally speaking its fine to send your whole entity to be updated, and this is how i would approach your situation potentially changing in the future if needed.

MVC 4 Web API NullException Error (Noobie)

I'm working on my first MVC 4 app, following the MVC First Web API Tutorial on Asp.net. I've left the names the same, but changed the model and controller code. Here's my model:
public class Product
{
public string SID { get; set; }
public string name { get; set; }
public string givenName { get; set; }
public string sn { get; set; }
public string mail { get; set; }
public string telephoneNumber { get; set; }
public string mobile { get; set; }
public string otherMobile { get; set; }
public string title { get; set; }
public string Manager { get; set; }
public DateTime whenChanged { get; set; }
}
public class ProductModel
{
public ProductModel()
{
ProductList = new List<Product>();
}
public IList<Product> ProductList { get; set; }
}
And here's my APIcontroller:
public class ProductsController : ApiController
{
ProductModel products = new ProductModel();
public IEnumerable<Product> GetAD()
{
DirectoryEntry domainRoot = new DirectoryEntry(LDAP_server);
DirectorySearcher searcher = new DirectorySearcher(searchStr);
SearchResultCollection results = searcher.FindAll();
foreach (SearchResult srchResult in results)
{
DirectoryEntry dirEntry = srchResult.GetDirectoryEntry();
if (dirEntry.Properties["givenName"].Value != null && dirEntry.Properties["sn"].Value != null && !dirEntry.Parent.Name.Contains("Terminated"))
{
products.ProductList.Add(new Product()
{
SID = dirEntry.Properties["sid"].Value.ToString(),
name = dirEntry.Properties["name"].Value.ToString(),
givenName = dirEntry.Properties["givenName"].Value.ToString(),
sn = dirEntry.Properties["sn"].Value.ToString(),
mail = dirEntry.Properties["mail"].Value.ToString(),
telephoneNumber = dirEntry.Properties["telephoneNumber"].Value.ToString(),
mobile = dirEntry.Properties["mobile"].Value.ToString(),
otherMobile = dirEntry.Properties["otherMobile"].Value.ToString(),
title = dirEntry.Properties["title"].Value.ToString(),
Manager = dirEntry.Properties["Manager"].Value.ToString(),
whenChanged = Convert.ToDateTime(dirEntry.Properties["whenChanged"].Value.ToString()),
});
}
}
return products.ProductList;
}
}
I'm getting the NullException on 'products.ProductList.Add(new Product()', am I missing something simple? Please forgive my coding, as I'm just trying to get this up and running, thanks.
the problem mostly likely is dealing with dirEntry, not Web API itself. rather than introduce LDAP into this, just create a bunch of dummy products to return.
FYI... there is also a memory leak issue with the use of LDAP objects. They need to be properly disposed of, both along the happy path and if an exception is thrown.
I'm an idiot. 'sid' is not the correct property name from AD, it is 'objectSid', thus always returning a null. I knew it was something simple.

Resources