I am creating a Poll in my ASP.NET MVC project.
1) I select poll and it's replies as an object of Poll model from database [poll model contain a list of reply model that named PollReplies]:
Poll model:
public class Poll
{
public Poll() {
PollReplies = new List<PollReply>();
}
public int ID { get; set; }
public System.DateTime CDate { get; set; }
public System.DateTime SDate { get; set; }
public System.DateTime EDate { get; set; }
public string User_ID { get; set; }
public string Title { get; set; }
public int Language_ID { get; set; }
public bool IsActive { get; set; }
public bool IsPublic { get; set; }
public bool ResultIsPublic { get; set; }
public List<PollReply> PollReplies { get; set; }
}
Reply model:
public class PollReply
{
public int ID { get; set; }
public int Poll_ID { get; set; }
public string Title { get; set; }
public int Count { get; set; }
public bool IsChecked { get; set; }
}
2) I render poll title of the selected poll object as question of poll.
3) With a for render replies:
for (int i = 0; i < Model.PollReplies.Count; i++)
{
#Html.HiddenFor(model => model.PollReplies[i].ID, new { #Value = Model.PollReplies[i].ID })
counter++;
<tr>
<td>#counter</td>
<td>#Html.DisplayFor(model=>model.PollReplies[i].Title)</td>
<td>
#Html.RadioButtonFor(model => model.PollReplies[i].IsChecked,counter)
</td>
</tr>
}
My problem:
1) When I submit form, The Poll model is contain all replies. All replies has ID but the IsChecked propery of replies not set with the client selected radiobutton!(all IsChecked of replies are false) How I can post the selected reply as true?
2) I am using #Html.RadioButtonFor and radios give name attributes automaticly, so the name attribute of generated inputs are diffrente, but i need to just select one of radios! What is the best solution?
Related
I have customer model
public class Customer
{
public Customer()
{
this.SystemValues = new HashSet<SystemValue>();
}
public string Name { get; set; }
public Nullable<System.Guid> GUID { get; set; }
public int Id { get; set; }
public virtual ICollection<SystemValue> SystemValues { get; set; }
}
and systemValue model
public class SystemValue
{
public int CustomerId { get; set; }
public int SystemValueId { get; set; }
public Nullable<int> SystemValueCategoryId { get; set; }
public string SystemValueType { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string TextValue { get; set; }
public Nullable<int> IntValue { get; set; }
public Nullable<double> FloatValue { get; set; }
public byte[] BlobValue { get; set; }
public Nullable<System.DateTime> DateTimeValue { get; set; }
public Nullable<bool> BooleanValue { get; set; }
public Nullable<int> LookupValueId { get; set; }
public Nullable<int> LookupValueGroupId { get; set; }
public Nullable<bool> IsReadonly { get; set; }
public bool IsHidden { get; set; }
public int Id { get; set; }
public virtual Customer Customers { get; set; }
}
in which way I could show a link in CustomerView(CustomersController) foreach customer that redirect to the SystemValuesView(SystemValuesController) with related to this customer SystemValues?
I found out one way - redirect to this controller's action with parameter.
public ActionResult ViewSystemValues(int? id)
{
return RedirectToAction("Index", "SystemValues", new {id});
}
But I'm sure there must be smarter way.
#for(int i = 0; i < Model.yourcustomerlist.Count(); i++)
{
<tr>
<td>
<a class="btn btn-primary" href="#Url.Action("Index", "SystemValues", new { id = Model.yourcustomerlist[i].CustomerId })">
<b>Go to system values</b>
</a>
</td>
</tr>
}
I hope I understood you correctly.
This code should go in the view. The view should be strongly typed to a model.
Code is if you want a button that redirects to the index view of the SystemValues controller, with the CustomerId as input. You should change "yourcustomerlist" to the list containing the customer information. If it's not part of a table, remove the table-related tags (<td> and <tr>).
I am trying to insert data into a sql server temporary table based on a value picked from a dropdownlist. In my model I have 4 classes:
public class Customer
{
[Key]
public int CustID { get; set; }
public string CustName { get; set; }
public virtual ICollection<Sale> Sales { get; set; }
}
}
public class Product
{
[Key]
public int ProductID { get; set; }
public string ProductName { get; set; }
public decimal Price { get; set; }
public virtual ICollection<Sale> Sales { get; set; }
}
}
public class Sale
{
[Key]
public int RecordID { get; set; }
public int ProductID { get; set; }
public int CustID { get; set; }
public int InvoiceNo { get; set; }
public int Quantity { get; set; }
public virtual Customer Customer { get; set; }
public virtual Product Product { get; set; }
}
public class TempTable
{
[Key]
public int recordID { get; set; }
public string CustName { get; set; }
public string PoductName { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public int InvoiceNo { get; set; }
}
In my SaleController I have the following action:
public ActionResult OldInvoice(Sale sale)
{
ViewBag.InvoiceNo = new SelectList(db.Sales, "RecordID", "InvoiceNo", sale.RecordID);
return View();
}
[HttpPost]
public ActionResult OldInvoice(TempTable t, int InvoiceNoToSearch = 0)
{
var query = (from s in db.Sales
join c in db.Customers on s.CustID equals c.CustID
join p in db.Products on s.ProductID equals p.ProductID
where s.InvoiceNo.Equals(s.InvoiceNo == InvoiceNoToSearch)
select new
{
s.InvoiceNo,
s.Quantity,
c.CustName,
p.ProductName,
p.Price
}).ToList();
foreach (var temp in query)
{
t.CustName = temp.CustName;
t.InvoiceNo = temp.InvoiceNo;
t.PoductName = temp.ProductName;
t.Price = temp.Price;
t.Quantity = temp.Quantity;
db.TempTables.Add(t);
db.SaveChanges();
}
return RedirectToAction("OldInvoice");
}
and finally my view is:
#model IEnumerable<UsingDropDownListValueInQuery.Models.Sale>
#{
ViewBag.Title = "OldInvoice";
}
<h2>OldInvoice</h2>
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
#Html.DropDownList("InvoiceNo")
<p>
<input type="submit" value="Save" />
</p>
}
I get the following error:
Unable to cast the type 'System.Boolean' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types.
If I enter in the Where Statement an Existing InvoiceNo it does the job but not if I try to pick the value from the dropdownlist
The problem seems to be that you're never actually sending the value back. In your view, you've created a select named "InvoiceNo", but in your post action, you don't have any parameters that can accept that value. The closest and probably the one you intend to bind to is InvoiceNoToSearch, but if that's the variable you want to use, your view needs to match:
#Html.DropDownList("InvoiceNoToSearch")
Of course, that means your SelectList in ViewBag no longer binds automatically as the options for that select, but that can be fixed by just explicitly specifying it:
#Html.DropDownList("InvoiceNoToSearch", (SelectList)ViewBag.InvoiceNo)
I'm displaying the data from a table called gigs, however it contains a couple of foreign keys to tables 'Bands' and 'Venues' so when using this code in my controller,
string user = User.Identity.GetUserId();
var yourgigs = (from g in dbg.gigs
from v in dbg.Venues
from b in dbg.Bands
from ga in g.gigsaccasses
where (ga.Id == user &&
v.venueid == g.venueid &&
b.bandid == g.bandid)
select g);
return View(yourgigs);
it's displaying bandid and venueid in the view which are meaningless integers. How would I replace those with what I suppose would be b.bandname, v.venuename and also add v.address1 and v.city? The SQL statement that does this is
SELECT bands.bandname, venues.venuename, venues.address1, venues.city, gigs.whatdate, gigs.starttime
FROM gigs INNER JOIN
bands ON gigs.bandid = bands.bandid INNER JOIN
gigsaccass ON gigs.gigid = gigsaccass.gigid INNER JOIN
dbo.AspNetUsers ON gigsaccass.Id = dbo.AspNetUsers.Id INNER JOIN
venues ON gigs.venueid = venues.venueid
WHERE dbo.AspNetUsers.Id = //some user//
I did try using anonymous types as such:
var yourgigs = (from g in dbg.gigs
from v in dbg.Venues
from b in dbg.Bands
from ga in g.gigsaccasses
where (ga.Id == user &&
v.venueid == g.venueid &&
b.bandid == g.bandid
select new
{
bandname = b.bandname,
venuename = v.venuename,
address1 = v.address1,
city = v.city,
whatdate = g.whatdate,
starttime = g.starttime
});
But this then threw an error:
The model item passed into the dictionary is of type 'System.Data.Entity.Infrastructure.DbQuery1[<>f__AnonymousType76[System.String,System.String,System.String,System.String,System.DateTime,System.TimeSpan]]', but this dictionary requires a model item of type 'System.Collections.Generic.IEnumerable`1[OnStageTonight_MVC.Models2.gigs]'.
The View is expecting type 'gigs'
#model IEnumerable<OnStageTonight_MVC.Models2.gigs>
#{
ViewBag.Title = "Gigs";
}
<h2>Gigs</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.venueid)
</th>
<th>
#Html.DisplayNameFor(model => model.bandid)
</th>
What am I missing?
EDIT:
I should add that I do have a model, but I'm assuming this is what is at fault.
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity;
using System.Linq;
using System.Web;
namespace OnStageTonight_MVC.Models2
{
[Table("gigs")]
public partial class gigs
{
public gigs()
{
this.gigsaccasses = new HashSet<gigsaccass>();
}
[Key]
public int gigid { get; set; }
public int venueid { get; set; }
public int bandid { get; set; }
[Display(Name="Date")]
public System.DateTime whatdate { get; set; }
[Display(Name="Starts at")]
public System.TimeSpan starttime { get; set; }
public virtual ICollection<gigsaccass> gigsaccasses { get; set; }
}
[Table("gigsaccass")]
public partial class gigsaccass
{
[Key]
public int gigaccassid { get; set; }
public int gigid { get; set; }
public string Id { get; set; }
public virtual gigs gig { get; set; }
public virtual AspNetUsers AspNetUser { get; set; }
}
[Table("dbo.AspNetUsers")]
public class AspNetUsers
{
[Key]
public string Id { get; set; }
public string Email { get; set; }
public bool EmailConfirmed { get; set; }
public string PasswordHash { get; set; }
public string SecurityStamp { get; set; }
public string PhoneNumber { get; set; }
public bool PhoneNumberConfirmed { get; set; }
public bool TwoFactorEnabled { get; set; }
public Nullable<System.DateTime> LockoutEndDateUtc { get; set; }
public bool LockoutEnabled { get; set; }
public int AccessFailedCount { get; set; }
public string UserName { get; set; }
public string YourName { get; set; }
public List<gigsaccass> gigsaccasses { get; set; }
}
[Table("venues")]
public partial class venues
{
[Key]
public int venueid { get; set; }
[Required]
[Display(Name = "Venue")]
public string venuename { get; set; }
[Required]
[Display(Name = "Address")]
public string address1 { get; set; }
[Required]
[Display(Name = "City")]
public string city { get; set; }
public List<gigs> venuegigs { get; set; }
}
[Table("bands")]
public class bands
{
[Key]
public int bandid { get; set; }
[Required]
[Display(Name = "Name")]
public string bandname { get; set; }
public List<gigs> bandgigs { get; set; }
}
public partial class gigscontext : DbContext
{
public gigscontext()
: base("DefaultConnection")
{
}
public DbSet<gigs> gigs { get; set; }
public DbSet<gigsaccass> gigsaccass { get; set; }
public DbSet<AspNetUsers> AspNetUsers { get; set; }
public DbSet<venues> Venues { get; set; }
public DbSet<bands> Bands { get; set; }
}
}
You can't use anonymous classes here. Your view needs to know how to work with model, it needs type information, but: "The type name is generated by the compiler and is not available at the source code level"
You can't pass such objects around. http://www.codeproject.com/Articles/15624/Inside-C-Anonymous-Methods#5
You need to create class that represent row in your data set and return list of populated objects.
As less preferred alternative you can use dynamic: https://msdn.microsoft.com/en-us/library/dd264736.aspx
The M in MVC stands for model, and what you want is one of the 3 main tenants of MVC.
You want an object that encapsulates all the information to be displayed on the view.
It is considered best practice to create a model for the view. This is an additional layer which separates the storage of the item (your entity model) from it's presentation.
var yourgigs = (from g in dbg.gigs
from v in dbg.Venues
from b in dbg.Bands
from ga in g.gigsaccasses
where (ga.Id == user &&
v.venueid == g.venueid &&
b.bandid == g.bandid
select new GigViewModel
{
bandname = b.bandname,
venuename = v.venuename,
address1 = v.address1,
city = v.city,
whatdate = g.whatdate,
starttime = g.starttime
});
public class GigViewModel
{
public string bandname { get; set; }
public string venuename { get; set; }
public string address1 { get; set; }
public string city { get; set; }
public DateTime whatdate { get; set; }
public Timespan starttime { get; set; }
}
When persisting data from your view models, use AutoMapper or something similar to copy properties with matching names between your view models and your entity models.
Use the new view model in your view:
#model IEnumerable<OnStageTonight_MVC.Models2.GigModelView>
this is my model
public class Post
{
public long PostID { get; set; }
[Required]
[MaxLength(255)]
public string Title { get; set; }
}
public class Tag
{
public long TagID { get; set; }
[Required]
[Display(Name = "Tag Name")]
[MaxLength(30)]
public string TagName { get; set; }
public bool IsActive { get; set; }
}
public class TagPost
{
public long TagPostID { get; set; }
public long PostID { get; set; }
public long TagID { get; set; }
[ForeignKey("PostID")]
public virtual Post Posts { get; set; }
[ForeignKey("TagID")]
public virtual Tag Tags { get; set; }
}
1) Is this the right many to many configuration in EF 4.1 without mentioning the modelbinder for many to many.
2) if i have completed the many to many configuration using dataannotation why the data is not inserting in tagpost .
public void InsertPostQuestion(Post post,List<string> tags)
{
context.Posts.Add(post);
foreach (string tag in tags)
{
Tag tagr = new Tag();
tagr.TagName = tag;
tagr.IsActive = true;
context.Tags.Add(tagr);
}
context.SaveChanges();
}
3) I do have to define modelbinder to have many to many inserts or delete or update?
modelBuilder.Entity<Post>().
HasMany(c => c.Tags).
WithMany(p => p.Posts).
Map(
m =>
{
m.MapLeftKey("PostID");
m.MapRightKey("TagID");
m.ToTable("TagPost");
});
Change your models to this:
public class Post
{
public long PostID { get; set; }
[Required]
[MaxLength(255)]
public string Title { get; set; }
public bool IsActive { get; set; }
public virtual List<Tag> Tags { get; set; }
}
public class Tag
{
public long TagID { get; set; }
[Required]
[Display(Name = "Tag Name")]
[MaxLength(30)]
public string TagName { get; set; }
public bool IsActive { get; set; }
public virtual List<Post> Posts { get; set; }
}
and then save like so:
public void InsertPostQuestion(Post post,List<string> tags)
{
context.Posts.Add(post);
foreach (string tag in tags)
{
// TODO: If tag has a unique index on TagName, see if it exists first
Tag tagr = new Tag();
tagr.TagName = tag;
tagr.IsActive = true;
context.Tags.Add(tagr);
post.Tags.Add(tagr);
}
context.SaveChanges();
}
EF will create the intermediate table in the db and populate it nicely automatically.
My model classes are:
public class User
{
public User()
{
Polls = new List<Poll>();
}
public int Id { get; set; }
public String FirstName { get; set; }
public String LastName { get; set; }
ICollection<Poll> Polls { get; set; }
}
public class Poll
{
public int Id { get; set; }
public int PositiveCount { get; set; }
public int NegativeCount { get; set; }
public String Description { get; set; }
public User User { get; set; }
}
public class PollsContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Poll> Polls { get; set; }
}
EF created a table User_Id column for Polls table.
In the Create view of the Poll, I want to specify the UserId for new poll belongs too, but intellisense shows there is no access to model.UserId, there is a model.User.Id, which is not allowing me create a Poll for existing user and rather creates new User with new Id and no association is created.
<div class="editor-label">
#Html.LabelFor(model => model.User.Id)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.User.Id)
#Html.ValidationMessageFor(model => model.User.Id)
</div>
What is the right way of creating a new Poll for an existing User then ?
public class Poll
{
public int Id { get; set; }
public int PositiveCount { get; set; }
public int NegativeCount { get; set; }
public String Description { get; set; }
public int UserId { get; set; }
public User User { get; set; }
}
I think your Poll class should look like:
public class Poll
{
public int Id { get; set; }
public int PositiveCount { get; set; }
public int NegativeCount { get; set; }
public String Description { get; set; }
public int User_Id { get; set; }
public User User { get; set; }
}
If you have a column in your Poll table User_Id, then your model should also have this column. You can then just assign a User_Id to a Poll and Entity Framework will take care of the correct linking to the right User object.
Further, consider making your association properties (Poll.User and User.Polls) virtual in order to use the lazy loading mechanisms of Entity Framework.
See this