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.
Related
I'm using asp.net core Identity. The user ID will be as FK in the Invite model and I'm trying to display all the users that are in the invite
Models
public class Invite
{
public int ID { get; set; }
[ForeignKey("UserId")] //ICollection<Invite> in User
[Display(Name = "Users")]
public virtual ApplicationUser User { get; set; }
}
=================
public class ApplicationUser : IdentityUser
{
public string Description { get; set; }
[ForeignKey("GameID")]
public int? GameID { get; set; }
public string GameTag { get; set; }
public virtual ICollection<Invite> Invite { get; set; }
================
public class Game
{
public int ID { get; set; }
[Display(Name = "Game")]
public string GameName { get; set; }
public virtual ICollection<ApplicationUser> ApplicationUser { get; set; }//Allow Users to get Games FKID (Foreign key ID)
}
The getting the list of invites in the invite controller index and putting them inside viewbag for invite razor index page
this is where the error is coming from
if (i.User == tu.Id)
// GET: Invites
public async Task<IActionResult> Index()
{
ViewBag.InviteList = new List<String>();
var invite = _context.Invites;
var theuser = _context.ApplicationUser;
foreach (Invite i in invite)
{
foreach (ApplicationUser tu in theuser)
{
if (i.User == tu.Id)
{
ViewBag.InviteList.Add(tu.GameID + " " +tu.GameTag);
}
}
}
return View(await _context.Invites.ToListAsync());
}
Because i.User is an object of type ApplicationUser, it can't be compared to tu.Id which is (most likely) of type int.
You probably want to compare the IDs of the two ApplicationUser-Objects.
To do this, you need to use i.User.Id == tu.Id as the other comments have stated.
Maybe you meant to compare this
if (i.User == tu)
{
}
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. :)
I want to pass a value from the model...
#Html.HiddenFor(model => model.ProductId)
Exception thrown: 'System.ArgumentException' in System.Web.Mvc.dll
Additional information: Value cannot be null or empty.
But it is throwing this exception and I don't know why... And no ProductId isn't null.
Action
[HttpGet]
public ActionResult Edit(int ProductId = 0)
{
PCsViewModel pcViewModel = new PCsViewModel();
ProductRepository productRepo = new ProductRepository();
Product dbProduct = productRepo.GetAll(item=>item.ID==ProductId);
PCsRepository pcsRepo = new PCsRepository();
PC dbPC = pcsRepo.GetAll(item=>item.ProductID==ProductId);
if (dbProduct != null && dbPC != null)
{
pcViewModel = new PCsViewModel(dbProduct,dbPC);
}
return View(pcViewModel);
}
ViewModel
public int ProductId { get; set; }
[Required]
public string Name { get; set; }
public string PCsInfo { get; set; }//for the front view
[Required]
public double Price { get; set; }
[Required]
public string ImagePath { get; set; }
[Required]
public string Processor { get; set; }
[Required]
public string OS { get; set; }
[Required]
public int RAM { get; set; }
[Required]
public int Storage { get; set; }
[Required]
public string VideoCard { get; set; }
[Required]
public int CategoryID { get; set; }
public PCsViewModel()
{
}
public PCsViewModel(Product product, PC pc)
{
this.ProductId = product.ID;
this.CategoryID = product.CategoryID;
this.OS = product.OS;
this.Processor = product.Processor;
this.Name = product.Name;
this.RAM = product.RAM;
this.Storage = product.Storage;
this.VideoCard = pc.VideoCard;
this.PCsInfo = "PC "+product.Name + "with processor " + product.Processor;
this.Price = (double)product.Price;
this.ImagePath = Path.Combine(Constants.ImagesPCsDirectory, product.ImageName);
}
Based of the discussion in the comments, it looks like your actual issue wasn't related to the ProductId property but instead your ImagePath property, which was being passed into a Url.Content() helper (to resolve the appropriate path).
This would work as expected if the path existed, but if that property was null or empty, you would receive the ArgumentNullException that you currently are. The best approach would likely be to just only render the specific path if that specific property wasn't null:
#if (!string.IsNullOrEmpty(Model.ImagePath)) {
// Use Url.Content(Model.ImagePath) within here safely
}
There are multiple different ways to handle this, such as adding an additional property on your model to clean things up:
public bool HasImage => !string.IsNullOrEmpty(ImagePath);
And then use:
#if (Model.HasImage) {
// Use Url.Content(Model.ImagePath) within here safely
}
i have 3 model:
1st one:
public class CreateFieldModel
{
public FieldModel fm { get; set; }
public CategoryModel cm { get; set; }
}
2nd one:
public class FieldModel
{
public string field_Name { get; set; }
public InputTypeModel itm { get; set; }
public string input1 { get; set; }
public string input2 { get; set; }
public string input3 { get; set; }
public string input4 { get; set; }
public List<InputTypeModel> inputs { get; set; }
}
3rd One:
public class InputTypeModel
{
public string inputTypeName { get; set; }
public string inputTypeDesc { get; set; }
}
2 methods:
1st One:
public List<InputTypeModel> getInputTypes()
{
var inptypes = edu.InputTypes;
List<InputTypeModel> listInputTypes = new List<InputTypeModel>();
foreach (var inpType in inptypes)
{
listInputTypes.Add(new InputTypeModel { inputTypeName = inpType.Input_Type_Name, inputTypeDesc = inpType.Input_Type_Description });
}
return listInputTypes;
}
when this method executes listInputTypes has three different values.. i check it by debugging.. so no roblem here. This methos is under the class FormManagement.. I am calling this method from the following action method:
[HttpGet]
public ActionResult createNewField(CreateFieldModel cfm, string fcode)
{
FormManagement ffm = new FormManagement();
cfm.fm.inputs = ffm.getInputTypes();
return View(cfm);
}
when cfm.fm.inputs = ffm.getInputTypes(); executes it is showing "Object reference not set to an instance of an object." message... I am quite beginner to mvc.. please help
Without knowing what you really want to achieve with cfm-parameter in your action, the only thing I can suggest is to check for null references and create new instances before you assign them:
[HttpGet]
public ActionResult createNewField(CreateFieldModel cfm, string fcode)
{
FormManagement ffm = new FormManagement();
if (cfm == null)
{
cfm = new CreateFieldModel();
}
if (cfm.fm == null)
{
cfm.fm = new FieldModel();
}
cfm.fm.inputs = ffm.getInputTypes();
return View(cfm);
}
Of course, this supposes that your not relying on incoming data through your route parameters. If you are, you need to check why the values are not getting passed in, but I'm guessing you don't need it as a parameter in the first place.
I have set up 3 models, code first and the relationships seem to be working but one is causing me a problem.
I have Article, Language and Edition Classes
public class Article
{
public int ID { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
}
public class Language
{
public int ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
public class Edition
{
public int ID { get; set; }
public Article Article { get; set; }
public Language Language { get; set; }
public string Title { get; set; }
public string Details { get; set; }
}
In my bootstrap/DBinitialiser, I can create Objects and populate them fine. The DB is created and the foreign keys for Language and Article are both present on the Edition table and correctly entered.
var engLang = new Language() {Code="en", Name="English Language"};
var altLang = new Language() {Code="xx", Name="Alternative Language"};
db.Languages.Add(engLang);
db.Languages.Add(altLang);
db.SaveChanges();
var testArt = new Article() { Name = "test" };
db.Articles.Add(testArt);
db.SaveChanges();
db.Editions.Add(new Edition(){Article = testArt, Language = engLang, Title="English Content"});
db.Editions.Add(new Edition(){Article = testArt, Language = altLang, Title="Alternative Content"});
db.SaveChanges();
I can now query the Editions and return a list of them, but the Language attribute is always NULL. The Article Attribute works fine.
var query = db.Editions.Where(r => r.Article.ID == Article.ID);
foreach (Edition item in query)
{
// item.Language => NULL
// item.Article => {Object Article}
}
I'm new to .net and Entity-Framework and can't work out why I always get this error.
I can even query by r => r.Language.ID == 1 and still get a NULL attribute on the Edition object.
Make sure you are using EF codefirst in right manner. Here you have some ambiguities. You must determine what relationships actually should exist, in your POCOs. Change classes like bellow:
public class Article
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Icon { get; set; }
}
public class Language
{
[Key]
public int ID { get; set; }
public string Name { get; set; }
public string Code { get; set; }
}
public class Edition
{
[Key]
public int ID { get; set; }
public virtual Article Article { get; set; }
public virtual Language Language { get; set; }
public string Title { get; set; }
public string Details { get; set; }
}
With thanks to AmirHossein Mehrvarzi for helping me write my models more clearly, I believe this error to be caused by the lazy loading of entities while iterating through the result of the query. ref: Entity Framework: There is already an open DataReader associated with this Command.
Without enabling MultipleActiveResultSets I simply added an Include statement to my linq
var query = db.Editions.Where(r => r.Article.ID == Article.ID).Include(r => r.Language);
foreach (Edition item in query)
{
// item.Language => {Object Language}
// item.Article => {Object Article}
}