I have an entity called Entity, (lol).
public class Entidad
{
[Key]
public int Id { get; set; }
public string Nombre { get; set; }
public virtual ICollection<Propiedad> Propiedades { get; set; }
}
I also have an entity called Properties
public class Propiedad
{
[Key]
public int Id { get; set; }
public virtual Entidad Entidad { get; set; }
public string Codigo { get; set; }
public string Nombre { get; set; }
public string TipoDeDatos { get; set; }
}
My Create view with the automated scaffolding gets rendered like this
http://screencast.com/t/aNU4tEH8EA1
However, I should be able to select the Entity from a dropdown list.
this is the automatically generated view
#model Inspinia_MVC5.Areas.GlobalAdmin.Models.Propiedad
#{
ViewBag.Title = "Create";
Layout = "~/Areas/GlobalAdmin/Views/Shared/_LayoutGlobalAdmin.cshtml";
}
<div class="row wrapper border-bottom white-bg page-heading">
<div class="col-sm-4">
<h2>Create</h2>
<ol class="breadcrumb">
<li>
#Html.ActionLink("List", "Index")
</li>
<li class="active">
<strong>Create</strong>
</li>
</ol>
</div>
<div class="col-sm-8">
<div class="title-action">
#Html.ActionLink("Back to List", "Index", null, new { #class = "btn btn-primary"})
</div>
</div>
</div>
<div class="wrapper wrapper-content animated fadeInRight">
<div class="row">
<div class="col-lg-12">
<div class="ibox float-e-margins">
<div class="ibox-title">
<h5>Create Propiedad</h5>
</div>
<div class="ibox-content">
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.Codigo, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Codigo)
#Html.ValidationMessageFor(model => model.Codigo)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Nombre, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Nombre)
#Html.ValidationMessageFor(model => model.Nombre)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.TipoDeDatos, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TipoDeDatos)
#Html.ValidationMessageFor(model => model.TipoDeDatos)
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-primary" />
#Html.ActionLink("Cancel", "Index", null, new { #class = "btn btn-white"})
</div>
</div>
</div>
}
</div>
</div>
</div>
</div>
</div>
Questions is how can I add the dropdown and make it fill the values from the entities?
You can't do that automatically.
You'll need to add a DropDownList to your View and add every entity you want to be selectable to this dropdown.
On the post, query for the entity, and then create Add the properties to it.
Also, check your controller, the default behavior for MVC is to create a child entity controller receiving the parent (in this case 'Entidad') id, make it receive only the model for semantics since you're not 'Entidad' specific in this case.
Related
I have a page written using some fake data in my controller, to render some mock data in my view. Here is the code I have:
Model
Data View Model
[Required]
[Display(Name = "Is this a remix?")]
public bool IsRemix { get; set; }
[Required]
[Display(Name = "Does this song contain sample(s)?")]
public bool ContainsSample { get; set; }
I had this in my ViewModel
public bool IsRemix { get; set; }
public bool ContainsSample { get; set; }
Controller
model.Songs = songs;
model.SongTitle = "Darkside of the Moon";
model.AlternativeSongTitle = "Wish You Were Here";
model.DurationMinutes = 3;
model.DurationSeconds = 57;
model.IsRemix = true;
model.ContainsSample = false;
View
<div class="form-group">
<label class="control-label col-md-4 pull-left" for="SongTitle">Is a Remix</label>
<div class="col-md-8">
<div class="admin-form theme-primary">
<div class="radio-custom radio-primary mt10 mr10 pull-left">
#Html.RadioButtonFor(m => m.IsRemix, true, new { #class = "control-label col-md-4" })
<label for="IsRemixYes">Yes</label>
</div>
<div class="radio-custom radio-primary mt10 pull-left">
#Html.RadioButtonFor(m => m.IsRemix, true, new { #class = "control-label col-md-4" })
<label for="IsRemixNo">No</label>
</div>
</div>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-4 pull-left" for="SongTitle">Contains Sample</label>
<div class="col-md-8">
<div class="admin-form theme-primary">
<div class="radio-custom radio-primary mt10 mr10 pull-left">
#Html.RadioButtonFor(m => m.ContainsSample, true, new { #class = "control-label col-md-4" })
<label for="ContainsSampleYes">Yes</label>
</div>
<div class="radio-custom radio-primary mt10 pull-left">
#Html.RadioButtonFor(m => m.ContainsSample, true, new { #class = "control-label col-md-4" })
<label for="ContainsSampleNo">No</label>
</div>
</div>
</div>
</div>
I am unsure how to get the radio buttons to be pre-selected.
I have a simple email form with TO, CC, BCC and another field for an attachment location i have the view working but i cant workout how to get all 3 ul lists to post to the controller
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<div class="form-group">
<label class="control-label col-md-2">To</label>
<div class="col-md-10">
<ul name="To" id="email-To"></ul>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Cc</label>
<div class="col-md-10">
<ul name="CC" id="email-Cc"></ul>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2">Bcc</label>
<div class="col-md-10">
<ul name="Bcc" id="email-Bcc"></ul>
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.FileName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.FileName, new { htmlAttributes = new { #class = "form-control" } })
</div>
</div>
<div class="pull-right">
<button type="submit" class="btn btn-success btn-xs">
<i class="fa fa-save"></i> Create
</button>
</div>
</div>
}
The model:
public System.Guid ID { get; set; }
public string To { get; set; }
public string CC { get; set; }
public string BCC { get; set; }
public string FileName { get; set; }
It will post the filename but not the ul's im guessing i would need to do some kind of json post for this kind of thing im not two sure?
I will be using the same partial across many different pages and the only thing that will be different is reference to the model (#model ...). I tried using "#model dynamic" so I can reference model in view, however lambdas that are in my partial that are referencing specific properties are throwing the following error:
"An expression tree may not contain a dynamic operation"
caused by the following reference to model:
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
How do structure my code or create a model reference that will work dynamically so that I can reference each specific model instance in my view pages? I tried many solutions online and nothing has worked so far. Below is my partial and view. Any help would be greatly appreciated!!!
Partial:
#model dynamic
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="container creative-containter-top">
<div class="row">
<div class="col-sm-offset-2 col-sm-8">
<div class="form-horizontal">
<div class="panel panel-primary">
<div class="panel-height pane panel-heading text-center">
<h3>#ViewBag.Title</h3>
</div>
<div class="panel-body">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Id)
<div class="form-group">
#Html.LabelFor(model => model.Name, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Name, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Code, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Code, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Code, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Code, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Code, new { htmlAttributes = new { #class = "checkbox center-block" } })
#Html.ValidationMessageFor(model => model.Code, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</div>
</div>
<div class="panel-footer">
#Html.ActionLink("Back to List", "Index")
</div>
</div>
</div>
</div>
</div>
</div>
}
View
#model CreativeNamingConvention.Models.Domain.CreativeOps
#{
ViewBag.Model = Model;
ViewBag.Title = "Edit Creative Ops Field";
}
#Html.Partial("~/Views/Templates/editBody.cshtml", Model)
check null from your action method or razor view
dynamic keyword in C# 4.0 allows you to do a dynamic model binding
dynamic viewModel = new ExpandoObject();
viewModel.TestString = "This is a test string";
return View(viewModel); for more in refer the below link
examles
Dynamic model binding with examle
Based on that message, I assume that you can't use the "For" suffixed methods with dynamic operations.
Never used them, but you could try the generic form:
#Html.Label("Name", "Name Label", htmlAttributes: new { #class = "control-label col-md-2" })
The syntax says expression, so I assume it would support dot notation.
I figured out a simple approach if you are ok with basic css and nothing fancy.
You can use "EditForModel()" to display all of the properties in your model instead of "EditFor" each property. After this, for each property that you do not want to have displayed in your view, you can add "[ScaffoldColumn(false)]" in the model as shown below. Thanks for all the advice!!!
Partial
#model dynamic
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="container creative-containter-top">
<div class="row">
<div class="col-sm-offset-4 col-sm-4">
<div class="form-horizontal">
<div class="panel panel-primary">
<div class="panel-height pane panel-heading text-center">
<h3>#ViewBag.Title</h3>
</div>
<div class="panel-body">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="col-sm-offset-2">
<div class="form-group">
#Html.EditorForModel()
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-primary" />
</div>
</div>
</div>
<div class="panel-footer">
#Html.ActionLink("Back to List", "Index")
</div>
</div>
</div>
</div>
</div>
</div>
}
Model
public partial class CreativeOps
{
public CreativeOps()
{
CreativeNames = new HashSet<CreativeNames>();
}
[ScaffoldColumn(false)]
public int Id { get; set; }
[Required]
public string Code { get; set; }
[Required]
public string Name { get; set; }
[Required]
public bool Disabled { get; set; }
public virtual ICollection<CreativeNames> CreativeNames { get; set; }
}
}
I'm having following FinanceProductFeatures table , I want show each of this table record as label name for a form.
So I created model class like this
public class ProductFinanceFeatures
{
public IList<AB_FinanceProductFeatures> ListProductFinanceFields { get; set; }
}
public partial class AB_FinanceProductFeatures
{
public string ProductFinanceNameEn { get; set; }
public string ProductFinance_Value_EN { get; set; }
}
then Controller class like this
[HttpGet]
public ViewResult Financing_Product_Feature_Configuration()
{
var model = new ProductFinanceFeatures
{
ListProductFinanceFields = db.FinanceProductFeatures.ToList()
};
return View(model);
}
then Its viewpage like this
#model albaraka.Models.ProductFinanceFeatures
#{
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#for (int i = 0; i < Model.ListProductFinanceFields.Count; i++)
{
<div class="form-group">
#Html.LabelFor(model => model.ListProductFinanceFields[i].ProductFinanceNameEn, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.TextAreaFor(m => m.ListProductFinanceFields[i].ProductFinance_Value_EN, new { #row = 5 })
</div>
</div>
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Save" class="btn btn-default" />
</div>
</div>
</div>
}
but here I'm not getting expected result, cannot render the Label
showing like this
Just simply replace TextAreaFor with DisplayFor as below-
<div class="col-md-10">
#Html.DisplayFor(m => m.ListProductFinanceFields[i].ProductFinance_Value_EN, new { #row = 5 })
</div>
Or
<div class="col-md-10">
#Html.DisplayTextFor(m => m.ListProductFinanceFields[i].ProductFinance_Value_EN)
</div>
Hope this works for you..!
I am fairly new to MVC5 and C# and I am trying to achieve something that I don't fully understand.
I have a Team Model such as this:
public class Team
{
[Key]
public Guid ID { get; set; }
public string TeamName { get; set; }
public string Coach { get; set; }
public string Conference { get; set; }
}
I also have a Player Model such as this:
public class Player
{
[Key]
public Guid Id { get; set; }
[ForeignKey("Teams")]
public Guid TeamId { get; set; }
public string Name { get; set; }
public virtual Team Teams { get; set; }
}
View Model is
public class TeamViewModel
{
public string TeamName { get; set; }
public string Coach { get; set; }
public string Conference { get; set; }
public List<Player> Players { get; set; }
}
With this structure, you are suppose to be able to add and infinite number of players to each team. As such I have a Teams table with few properties and a Player table that contains the player name as well as the player TeamId so that we know to what team they belong.
My problem comes when I am creating a team. I have Create Controller such as this:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(TeamViewModel model)
{
if (ModelState.IsValid)
{
var team = new Team { TeamName = model.TeamName, Coach = model.Coach, Conference = model.Conference, Player = model.Player };
db.Teams.Add(team);
var result = await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View();
}
And my View is as follows:
#model SoccerTeams.Models.ViewModels.TeamViewModel
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Team</h4>
<hr />
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="form-group">
#Html.LabelFor(model => model.TeamName, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.TeamName, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.TeamName, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Coach, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Coach, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Coach, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.Conference, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Conference, new { htmlAttributes = new { #class = "form-control" } })
#Html.ValidationMessageFor(model => model.Conference, "", new { #class = "text-danger" })
</div>
</div>
#if (#Model != null)
{
foreach (var p in Model.Player)
{
<div class="form-group">
#Html.Raw("<label class=\"control-label col-md-2\">" + p.ToString() + "</label>")
<div class="col-md-10">
#Html.Raw("<input class=\"form-control text-box single-line\" name=\"Player\" type-\"text\"")
</div>
</div>
}
}
else
{
<div class="form-group">
#Html.Raw("<label class=\"control-label col-md-2\">Player</label>")
<div class="col-md-10">
#Html.Raw("<input class=\"form-control text-box single-line\" name=\"Player\" type-\"text\"")
</div>
</div>
}
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
From my understanding, the View is suppose to be able to convert the input element to a list and pass it on to my ViewModel. However, my ViewModel is always coming up as null.
What am I missing and how would I make this work?
P.S. I understand that I can user Html.EditorFor, but I was not able to get it working, so I just printed it out as Html as I need to solve my other problem first.
Edit
I have altered my View to have the following code
<div class="form-group">
#Html.Raw("<label class=\"control-label col-md-2\">Player</label>")
<div class="col-md-10">
#Html.Raw("<input class=\"form-control text-box single-line\" name=\"model.Players[0].Name\" type-\"text\"")
</div>
</div>
As a result, the model now properly populates the Players Array, however all other values have now become null. If I remove the input element, the values are populated but players array is null again as there are no form fields for it. Do you know what could be the culprit?
In the TeamViewModel I have also renamed Player to Players.
In order for MVC to bind your form data to the Action method's parameters
their names should match.
Supposing your ViewModel has property for List<Player> Players your code should be:
In your case:
foreach (var p in Model.Player)
{
<div class="form-group">
#Html.Raw("<label class=\"control-label col-md-2\">" + p.ToString() + "</label>")
<div class="col-md-10">
#Html.Raw("<input class=\"form-control text-box single-line\" name=\"Player\" type-\"text\"")
</div>
</div>
}
Should be:
for (int i = 0; i < Model.Player.Length; i++)
{
<div class="form-group">
#Html.Raw("<label class=\"control-label col-md-2\">" + p.ToString() + "</label>")
<div class="col-md-10">
#Html.Raw("<input class=\"form-control text-box single-line\" name=\"model.Player[" + i + "].Name\" type-\"text\"")
</div>
</div>
}
Because this is the name of the parameter that you have provided:
Create(TeamViewModel model)
Also be careful because the indexes should not be broken, which means that they should be 0, 1, 2.. etc. without skipping a number.
The way that we read in the properties is by looking for
parameterName[index].PropertyName. The index must be zero-based and
unbroken.
NOTE You can read more about binding collections in Scott Hanselman's post - here
And last I suggest if you have a property that is list of something - in your case list of Player to use the plural form for the property name - Players.
EDIT
Try removing the "model." in front in the name. Make it like this "Players[0].Name". Since you only have one parameter in your Create Action method it should be fine.
I suggest you to use the helper #Html.EditorFor, so to do this you will create a partial view that will be used as template to inputs of the nested property. see the example:
Shared/EditorTemplates/Player.cshtml
#model Player
<div class="form-group">
#Html.HiddenFor(e => e.Id)
#Html.HiddenFor(e => e.TeamId)
<label class="control-label col-md-2" for="player">Player</label>
<div class="col-md-10">
#Html.TextBoxFor(e => e.Name, new { #class = "form-control text-box single-line", id = "player", name = "Player"})
</div>
</div>
Players form on Team view:
#Html.EditorFor(e => e.Player)
Instead of:
foreach (var p in Model.Player)
{
<div class="form-group">
#Html.Raw("<label class=\"control-label col-md-2\">" + p.ToString() + "</label>")
<div class="col-md-10">
#Html.Raw("<input class=\"form-control text-box single-line\" name=\"Player\" type-\"text\"")
</div>
</div>
}
See this article for more information about editor templates: Editor and display templates