How to bind nullable type items to the dropdownlist in razor view? - entity-framework-5

I am using MVC4 razor View engine, in my application I am trying to bind list of items to the dropdown list control. For some reasons and to avoid circular references I declared item type is nullable.
My Model:
public class Curriculum
{
public int CurriculumID { get; set; }
[Display(Name="Year")]
public int? SchoolYearID { get; set; }
public virtual SchoolYear SchoolYears { get; set; }
}
public class SchoolYear
{
public int SchoolYearID { get; set; }
[Display(Name="School Year"),MaxLength(250)]
public string Name { get; set; }
public virtual ICollection<Curriculum> Curriculums { get; set; }
}
In the above SchoolYearId is a FK and nullable type in Curriculum model.
My Controller:
public ActionResult Index(int id)
{
ViewBag.SchoolYear = new SelectList(db.SchoolYearRepository.GetAll().ToString(), "SchoolYearID", "Name");
ViewBag.Subject = new SelectList(db.SubjectRepository.GetAll().ToList(), "SubjectID", "Name");
return View();
}
My View:
#Html.DropDownListFor(model=>model.SchoolYearID, (IEnumerable<SelectListItem>)ViewBag.SchoolYear, "--")
While running my application throwing an error below:
DataBinding: 'System.Char' does not contain a property with the name 'SchoolYearID'.
Question: how can I resolve this type of problems how to bind nullable type objects to the dropdown list using razor view engine?
Please help me some one!

The problem is that I am binding a string to your DropDownList DataSource
ViewBag.SchoolYear = new SelectList(db.SchoolYearRepository.GetAll().ToString(), "SchoolYearID", "Name");
And a string doesn’t have a property SchoolYearID.
It Worked!
ViewBag.SchoolYear = new SelectList(db.SchoolYearRepository.GetAll().ToList(), "SchoolYearID", "Name");

Related

Applying weights to fields for ScoringProfile on a complex object

Hi I'm currently setting up my scoringProfile. I've marked by fields as "IsSearchable" as show below (Notice one field is a complex array).
public class MyIndexSchema
{
[IsSearchable] public int id { get; set; }
[IsSearchable] public string name { get; set; }
[IsSearchable] public string keywords { get; set; }
[IsSearchable] public Category[] category { get; set; }
}
public class Category
{
public int id { get; set; }
[IsSearchable] public string type { get; set; }
}
The weight I've defined is as below
var fieldWeights = new Dictionary<string, double>
{
{"name", 2},
{"category/type", 1}
};
But when i deploy my solution I'm seeing the following weights in the "Scoring profiles" tab on the selected index, but NOT the Category type field "category/type". What am I doing wrong?
To make the answer easier to be seen by others, I'm posting the answer revealed in comment:
This issue is a bug in the portal.The weights were properly applied even though its not showing up in the Portal.

How to get values from my injected class in MVC 5

I'm very new in MVC 5 and EF6 and need help please.
I have two classes and one single View, I can get the values of class Person but class Address is always null.
I tried use constructor and Bind in PersonController/Create
My classes:
public partial class Person
{
[Key]
public int PersonID { get; set; }
[Required]
[StringLength(40)]
public string Name { get; set; }
[StringLength(40)]
public string Email { get; set; }
public virtual Address AddressDI { get; set; }
}
public class Address
{
[Key]
public int AddressID { get; set; }
[Required]
public string City { get; set; }
[Required]
public string Street { get; set; }
[Required]
public virtual Person PersonDI { get; set; }
}
Controller
public class ContatoController : Controller
{
private readonly Address _address;
public PersonController()
{
_address = new Address();
}
HttpPost]
ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = #"Name,Email,AddressID,City,")] Person person, Address address)
{
if (ModelState.IsValid)
{
db.Person.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(person);
}
/* Other Actions and stuffs */
}
This is my 3 days pain :(
I don't know what exactly you're trying to achieve here. If you want to post a person class then just post the person:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Person person)
{
if (ModelState.IsValid)
{
db.Person.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(person);
}
and in the view, something like:
#model Partner
#Html.BeginForm("Create","Contato", FormMethod.Post){
#Html.TextboxFor(p => Model.AddressDI.City)
}
Also it is a common practice to send data across controller actions in wrapper classes referred to as viewModels. ViewModels usually contain everything that needs to be posted or displayed at a given moment in the view, as well as potential parameters for the view.
something like:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ContatoViewModel viewModel)
{
var person = new Person();
person.Name = viewModel.Name;
person.Email = viewModel.Email;
person.AddressDI = viewModel.AddressDI
if (ModelState.IsValid)
{
db.Person.Add(person);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(viewModel);
}
Being honest I can't say more without seeing what you're doing in the view.
More on MVVM pattern: https://msdn.microsoft.com/en-us/library/hh848246.aspx
There are tools available such as Jimmy Bogard's AutoMapper which help with copying the values between the view models and the classes.

How do I create a navigation property that can navigate to more than one entity type?

I have the following in my domain classes ( simplified )
public enum JobType
{
SalesOrder = 1,
StockOrder = 2
}
public class SalesOrder : LoggedEntity
{
public string Name { get; set; } // and other fields
}
public class StockOrder : LoggedEntity
{
public string Name { get; set; } // and other fields
}
public class Job : LoggedEntity
{
public int JobType { get; set; } // jobtype enum
public virtual LoggedEntity LinkedEntity { get; set; }
}
My context is as follows;
public class Context : DbContext
{
public DbSet<Job> Jobs { get; set; }
public DbSet<StockOrder> StockOrders { get; set; }
public DbSet<SalesOrder> SalesOrders { get; set; }
}
When I run the migration i get the error described [here][1] So using an abstract entity appears not to work.
My question was, how do I create a navigation property that can navigate to more than one entity type?
If JobType = SalesOrder then I want to navigate to sales order, if JobType = StockOrder then I want to navigate to stock order.
I wanted to use a Table Per Heirarchy Strategy [see TPH here][2]
The trick is to keep EF oblivious of the LoggedEntity class. Remodel your entities according to this example:
public enum JobType
{
SalesOrder = 1,
StockOrder = 2
}
public abstract class LoggedEntity
{
public int Id { get; set; }
public string Name { get; set; } // and other fields
}
public abstract class BaseOrder : LoggedEntity // New base class for orders!!
{ }
public class SalesOrder : BaseOrder
{ }
public class StockOrder : BaseOrder
{ }
public class Job : LoggedEntity
{
public JobType JobType { get; set; } // jobtype enum
public virtual BaseOrder Order { get; set; }
}
public class Tph2Context : DbContext
{
public DbSet<Job> Jobs { get; set; }
public DbSet<BaseOrder> Orders { get; set; }
}
You will see that the migration creates two tables, Jobs and BaseOrders (name to be improved). Job now has a property Order that can either be a SalesOrder or a StockOrder.
You can query specific Order types by
contex.Orders.OfType<StockOrder>()
And you will notice that EF doesn't know LoggedEntity, because
context.Set<LoggedEntity>()
will throw an exception
The entity type LoggedEntity is not part of the model for the current context.
how do I create a navigation property that can navigate
to more than one entity type?
You cannot do so. atleast not now. navigational properties are way of describing relationship between entities. at most, they represent, some sort of sql relationship. so you cannot alter or define such a relationship on the fly. you have to define it before hand.
Now in order to do that, you have to define separate navigational property for your separate conditions i.e.
public class Job : LoggedEntity
{
public int JobTypeSales { get; set; }
public int JobTypeStock { get; set; }
public virtual SalesOrder SalesOrder { get; set; }
public virtual StockOrder StockOrder { get; set; }
}
and then link them in configuration in modelbuilder through fluent API.
HasRequired(s => s.SalesOrder)
.WithMany()
.HasForeignKey(s => s.JobTypeSales).WillCascadeOnDelete(true);
HasRequired(s => s.StockOrder)
.WithMany()
.HasForeignKey(s => s.JobTypeStock).WillCascadeOnDelete(true);
and
as for your error "Sequence Contains No Elements"
this error comes, when the Linq query that you specified, is using either .First() or .Single(), or .ToList() and query returned no data.
so to avoid it use, .FirstOrDefault() or SingleOrDefault().
obviously with proper null check.

need help to map ViewModel to Entity using AutoMapper

I am new to automapper. need some help to map from ViewModel to Entity.
Here's my user entity
public class User
{
public int Id { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public DateTime CreatedDate { get; set; }
public string DisplayName { get; set; }
}
here's my ViewModel
public class UserViewModel
{
public string Email { get; set; }
public string Password { get; set; }
}
I create a map. its not working
CreateMap<UserLoginViewModel, User>()
.ForMember(dest=>dest.CreatedDate, DateTime.Now)
.ForMember(dest=>dest.DisplayName, "");
DisplayName and CreatedDate are required fields. since its not in the ViewModel, I will make DisplayName = "" and CreateDate = datetime.now.
I want to know if I can do it using the automapper, or I have to do it after the mapping.
please show me some sample code.
You mentioned that you have UserViewModel view model and User entity however your mapping configuration contains third type - UserLoginViewModel. Supposing that UserLoginViewModel is the same as UserViewModel, you should change you configuration as below.
Mapper.CreateMap<UserViewModel, User>()
.ForMember(dest=>dest.CreatedDate, t=> t.MapFrom(s=> DateTime.Now))
.ForMember(dest=>dest.DisplayName, t=> t.MapFrom(s=> ""));
AutoMapper wiki.

How do you exclude a property from being persisted in Azure Table storage?

If I have a class like this:
public class Facet : TableServiceEntity
{
public Guid ParentId { get; set; }
public string Name { get; set; }
public string Uri{ get; set; }
public Facet Parent { get; set; }
}
Parent is derived from the ParentId Guid, and that relationship is intended to be filled in by my repository. So how do I tell Azure to leave that field alone? Is there an Ignore attribute of some type, or do I have to create an inherited class that provides those relationships instead?
Using latest Microsoft.WindowsAzure.Storage SDK (v6.2.0 and up), the attribute name has changed to IgnorePropertyAttribute :
public class MyEntity : TableEntity
{
public string MyProperty { get; set; }
[IgnoreProperty]
public string MyIgnoredProperty { get; set; }
}
There is an attribute called WindowsAzure.Table.Attributes.IgnoreAttribute can be set on the property you want to exclude. Just use:
[Ignore]
public string MyProperty { get; set; }
It is a part of Windows Azure Storage Extensions, which you may download from:
https://github.com/dtretyakov/WindowsAzure
or install as a package:
https://www.nuget.org/packages/WindowsAzure.StorageExtensions/
The library is MIT licensed.
This reply from Andy Cross at bwc --- Thank you again Andy.
This question an azure forums
Hi,
Use the WritingEntity and ReadingEntity events. http://msdn.microsoft.com/en-us/library/system.data.services.client.dataservicecontext.writingentity.aspx This gives you all the control you need.
For reference there's a blog post linked off here too: http://social.msdn.microsoft.com/Forums/en-US/windowsazure/thread/d9144bb5-d8bb-4e42-a478-58addebfc3c8
Thanks
Andy
You may override the WriteEntity method in TableEntity and remove any properties that have your custom attribute.
public class CustomTableEntity : TableEntity
{
public override IDictionary<string, EntityProperty> WriteEntity(Microsoft.WindowsAzure.Storage.OperationContext operationContext)
{
var entityProperties = base.WriteEntity(operationContext);
var objectProperties = GetType().GetProperties();
foreach (var property in from property in objectProperties
let nonSerializedAttributes = property.GetCustomAttributes(typeof(NonSerializedOnAzureAttribute), false)
where nonSerializedAttributes.Length > 0
select property)
{
entityProperties.Remove(property.Name);
}
return entityProperties;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class NonSerializedOnAzureAttribute : Attribute
{
}
usage
public class MyEntity : CustomTableEntity
{
public string MyProperty { get; set; }
[NonSerializedOnAzure]
public string MyIgnoredProperty { get; set; }
}
You could also make the getter and setter non-public in order to skip the property from being saved in the table storage database.
See: https://stackoverflow.com/a/21071796/5714633

Resources