this is my models:
public class Ressource
{
[Key]
public int RessourceId { get; set; }
public string TitreR { get; set; }
public string Link { get; set; }
public string Type { get; set; }
public string Desc { get; set; }
public int Position { get; set; }
public int Rating { get; set; }
public string Tags { get; set; }
public int SectionId { get; set; }
public int UserId { get; set; }
}
public class Section
{
[Key]
public int SectionId { get; set; }
public string Titre { get; set; }
public String Tags { get; set; }
public virtual ICollection<Ressource> Ressources { get; set; }
}
public class structure
{
public Ressource ress;
public List<string> liste;
}
In this view, I enter the resource's title (TitreR), a description (Desc) and I choose from a list of tags which ones I want to link with this resource as well as entering a tag:
#model Mocodis.Models.structure
#{
ViewBag.Title = "AjouterRessource";
}
<h2>AjouterRessource</h2>
#using (Html.BeginForm("AjouterRessource", "Home", FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<input type="hidden" name="SectionId" value="#Model.ress.SectionId" />
<legend>Ressource</legend>
<div class="editor-label">
#Html.LabelFor(model => model.ress.TitreR)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ress.TitreR)
#Html.ValidationMessageFor(model => model.ress.TitreR)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.ress.Desc)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.ress.Desc)
#Html.ValidationMessageFor(model => model.ress.Desc)
</div>
</fieldset>
}
<form id="orderProductForm219" name="orderProductForm219" method="post" >
<b>Choisir les mots clés:</b>
<br /><br />
#foreach (string s in #Model.liste)
{
<input type="checkbox" name="tags[]" value="#s"> #s<br />
}
<input type="text" name="tags" id="tags" value="" />
<p>
<input type="submit" value="Create" />
<input type="hidden" name="tag" value="tags" />
<input type="hidden" name="res" value="#Model.ress" />
</p></form>
(I didnt put the javascript for it)
Finally the controllers are:
public ActionResult AjouterRessource(int SectionId)
{
Ressource res = new Ressource();
res.SectionId = SectionId;
Section sec = _db.Sections.Where(r => r.SectionId == SectionId).FirstOrDefault();
char[] delimiterChars = { ' ', ',', '.', ':', '\t' };
List<string> l = new List<string>();
l = sec.Tags.Split(delimiterChars).ToList();
structure s = new structure();
s.ress = res;
s.liste = l;
return View(s);
}
public string Check ( string list, string s)
{
char[] delimiterChars = { ' ', ',', '.', ':', '\t' };
List<string> l = new List<string>();
List<string> liste = new List<string>();
l = s.Split(delimiterChars).ToList();
liste = list.Split(delimiterChars).ToList();
foreach (string item in l)
{
if (!liste.Contains(item))
liste.Add(item);
}
return (string.Join(" ", liste.ToArray()));
}
[Authorize]
[HttpPost]
[InitializeSimpleMembership]
public ActionResult AjouterRessource(Ressource res, int SectionId, string tag)
{
if (ModelState.IsValid)
{
res.SectionId = SectionId;
var model = _db.Sections.Where(c => c.SectionId == SectionId).FirstOrDefault();
res.Tags = tag;
model.Tags = Check(model.Tags, tag);
_db.Entry(model).State = EntityState.Modified;
_db.Entry(res).State = EntityState.Added;
_db.SaveChanges();
return RedirectToAction("Section", new { SectionId = SectionId });
}
return View();
}
I keep getting: Object reference not set to an instance of an object on the line: #Html.ValidationSummary(true) in my view. Can you tell me how to fix it please?
Thank you
Every time I have gotten that error it has been from not initializing something. Looking through your code the only spot I am seeing that might need it is when you are setting structure. You might try putting a constructor on that class to initialize the fields and see if that helps. something like
public structure()
{
ress = new Resource();
liste = new List<string>();
}
You probably need to add the { get; set; } to the resource and list under structure as well. Hopefully this helps.
Related
I have a DropDownListFor that doesn't seem to be setting the expected Model property. Here's the HTML:
#using (Html.BeginForm())
{
#Html.DropDownListFor(x => x.SelectedItem,
new SelectList(Model.ItemList, "Id", "Desc"), null,
new { #class = "selected-list", #size = "3" });
<div>
#Model.SelectedItem
</div>
<input type="submit" value="Do Stuff"
asp-controller="My"
asp-action="DoStuff"
asp-route-itemId="#Model.SelectedItem" />
</div>
}
The div is just there for debugging purposes, and it either shows 0 or blank.
The underlying model has a property:
public int SelectedItem { get; set; }
I've also tried a string:
public string SelectedItem { get; set; } = String.Empty;
(Hence why 0 or blank)
The actual list itself displays fine, it just doesn't update the model on select. How can I get it to update the model?
If you use asp-route-itemId, your action need contains parameter named itemId to receive the value. But for your scenario, it seems to be useless to receive such value, because it will always receive the value you set instead of the dropdown changed value.
Here is a simple demo you could follow and check if any difference with yours:
Model
public class TestVM
{
public string SelectedItem { get; set; } = String.Empty;
public List<Item> ItemList { get; set; }
}
public class Item
{
public int Id { get; set; }
public string Desc { get; set; }
}
View(Index.cshtml)
#model TestVM
#using (Html.BeginForm())
{
#Html.DropDownListFor(x => x.SelectedItem,
new SelectList(Model.ItemList, "Id", "Desc"), null,
new { #class = "selected-list", #size = "3" });
<div>
#Model.SelectedItem
</div>
<input type="submit" value="Do Stuff"
asp-controller="Home"
asp-action="DoStuff" />
}
Controller
[HttpGet]
public IActionResult Index()
{
//Note: hard-coded the model just for easy testing.....
var model = new TestVM()
{
SelectedItem = "1",
ItemList = new List<Item>()
{
new Item(){Id=1,Desc="aa"},
new Item(){Id=2,Desc="bb"},
new Item(){Id=3,Desc="cc"}
}
};
return View(model);
}
[HttpPost]
public IActionResult DoStuff(TestVM model)
{
return View("index", model);
}
Result
Im trying to pass values from view to controller using Vue.js, but Im getting a problem with decimal values only. When I input decimal values and post it to controller, it arrives NULL.
Note: Only for decimal values, to Integer or String values it's ok.
Here is my code:
salvarProdutos: function () {
load();
this.$http.post(urlInit + '/Quotation/updateInfoComercial/', {
RefCotacao: this.refCotacao,
//InformaçoesComerciais//
Qtd: this.quantidade,
UnidadeMedida: this.unidadeMedida,
ValorUnitario: this.valorUnitarioProduto,
LoteMinimo: this.loteMinimo,
PrazoEntrega: this.prazoEntrega,
PorcentagemMaxVariacao: this.porcentagemVariacao
//--------------------------//
}).then((response) => {
unload();
if (response.data.worked) {
alert("Dados salvos com sucesso!");
}
else {
alert("Erro - Tente novamente mais tarde.");
}
});
}
<div class="col-md-6">
<div class="form-group label-floating">
<label class="control-label" for="porcentagemVariacao">
Porcentagem máxima de variação
</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text">%</span>
</div>
<input type="number" min="1" step="0.1" class="form-control" id="porcentagemVariacao" v-model="porcentagemVariacao" required>
<span class="material-input"></span>
</div>
</div>
</div>
Here is my Controller:
[HttpPost]
public ActionResult updateInfoComercial(string refCotacao, InformacoesComerciais infoCF, string form)
{
var partNumber = infoCF.PartNumber;
var porcentagem = infoCF.PorcentagemMaxVariacao;
var message = "";
message = "OK";
return Json(new { message = message }, JsonRequestBehavior.AllowGet);
}
Here is my model:
public partial class InformacoesComerciais
{
public InformacoesComerciais() { }
[DatabaseGenerated(DatabaseGeneratedOption.None)]
//public int ID { get; set; }
public decimal? Qtd { get; set; }
[StringLength(8)]
public string UnidadeMedida { get; set; }
[Key]
[Column(Order = 1)]
[StringLength(20)]
public string RefCotacao { get; set; }
public decimal? ValorUnitario { get; set; }
public decimal? LoteMinimo { get; set; }
public decimal? PorcentagemMaxVariacao { get; set; }
//[Column(TypeName = "date")]
public string PrazoEntrega { get; set; }
}
I change the <globalization> tag in Web.config and works:
Before:
<globalization culture="pt-BR" uiCulture="pt-BR" />
After:
<globalization culture="en-US" uiCulture="en-US" />
Thanks.
This is my form in contact class
<form method="POST">
<fieldset>
<div class="form-group">
<input class="form-control" placeholder="E-mail" name="subid" autofocus="">
</div>
<button href="" class="btn btn-gm btn-success">View</button>
</fieldset>
This is my code in controller and i have view called Contact
[HttpGet]
public ActionResult Contact()
{
return View();
}
[HttpPost]
public ActionResult Contact(string subid)
{
try
{
var webClient = new WebClient();
string url = string.Format(BASE_URL + "Subjectstatus/{0}", subid);
var json = webClient.DownloadString(url);
var js = new JavaScriptSerializer();
ViewBag.attendlist = js.Deserialize<List<attendlist>>(json);
return View();
}
catch
{
ViewBag.con = "gg";
return null;
}
}
This is my attendlist class
public class attendlist
{
[Display(Name = "ID")]
public string sid { get; set; }
[Display(Name = "Name")]
public string name { get; set; }
[Display(Name = "Subject")]
public string sub { get; set; }
[Display(Name = "Date")]
public string date { get; set; }
}
This is Contact View im trying to loop it using for each
#foreach (var dd in ViewBag.attendlist)
{
<h3>#dd.ID</h3>
}
This is the error when im try to load contact view
[HttpGet]
public ActionResult Contact()
{
return View( new ViewContact() );
}
[HttpPost]
public ActionResult Contact(ViewContact contact)
{
try
{
var webClient = new WebClient();
string url = string.Format(BASE_URL + "Subjectstatus/{0}", contact.subid);
var json = webClient.DownloadString(url);
var js = new JavaScriptSerializer();
attendlist list= js.Deserialize<attendlist>(json)
contact.attendlist = list;
return View(contact);
}
catch
{
ViewBag.con = "gg";
return null;
}
}
Class ViewContact
public class ViewContact
{
public attendlist list { get; set; }
public string subid { get; set; }
}
And the foreach at the view
foreach(var dd in Model.list){
//your html view code
}
The view
<form method="POST">
<fieldset>
<div class="form-group">
#Html.TextBoxFor(m => m.subid, new { #class = "form-control", #placeholder = "Email" }) >
</div>
<button href="" class="btn btn-gm btn-success">View</button>
</fieldset>
*Note textboxfor , get the model atributte and it bind later it correctly to the action submit
*Note that now you have to pass a contect not a string to Contact(ViewContact contact) action
I would like to know if I can convert my div button group (btn-group) to razor syntax in my asp.net mvc app? I want the razor syntax so I can preselect and pre activate a button label when entering the page. If razor isn't needed, then can someone please show me how to make a button active and selected on the page being entered from my view model data? It seems that without razor I would have to pass my viewmodel data to javascript to perform, but that doesn't seem right. Here is my html
<div class="form-group">
#Html.LabelFor(model => model.Listing.SpaceType, htmlAttributes: new { #class = "control-label" })
<div class="btn-group form-control" data-toggle="buttons" id="SpaceType">
<label id="SpaceTypeLabel0" class="btn btn-primary">
<input type="radio" name="typeoptions" autocomplete="off" id="0"> House
</label>
<label id="SpaceTypeLabel1" class="btn btn-primary">
<input type="radio" name="typeoptions" autocomplete="off" id="1"> Apartment
</label>
<label id="SpaceTypeLabel2" class="btn btn-primary">
<input type="radio" name="typeoptions" autocomplete="off" id="2"> Studio
</label>
<label id="SpaceTypeLabel3" class="btn btn-primary">
<input type="radio" name="typeoptions" autocomplete="off" id="3"> Other
</label>
</div>
</div>
Here is my model
public class Space
{
public int SpaceId { get; set; }
public virtual SpaceOverview Overview { get; set; }
public virtual SpaceDetails Details { get; set; }
public virtual SpaceListing Listing { get; set; }
public virtual SpaceAddress Address { get; set; }
[Required]
public DateTime DateCreated { get; set; }
}
and spacelisting is
public class SpaceListing
{
[Key, ForeignKey("SpaceOf")]
public int SpaceListingId { get; set; }
public SpaceType SpaceType { get; set; }
public SpaceLocation SpaceLocation { get; set; }
public SpaceAccommodation Accommodation { get; set; }
public Space SpaceOf { get; set; } // one-to-one
}
and spacetype is
public enum SpaceType
{
Home,
Apartment,
Studio,
Park,
Beach,
Field,
Backyoard,
FrontYard,
Other
}
Currently you creating a group of radio buttons with name="typeoptions" which have no relationship to the model, and your not even giving the radio buttons a value attribute so nothing would post back anyway.
The syntax should be
#Html.RadioButtonFor(m => m.Listing.SpaceType, "House", new { id = "House" })
#Html.Label("House")
#Html.RadioButtonFor(m => m.Listing.SpaceType, "Apartment", new { id = "Apartment" })
#Html.Label("Apartment")
...
To make this easier, you can create an extension method
public static class RadioButtonHelper
{
public static MvcHtmlString EnumRadioButtonListFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
{
ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
string name = ExpressionHelper.GetExpressionText(expression);
Type type = Nullable.GetUnderlyingType(metaData.ModelType);
if (type == null || !type.IsEnum)
{
throw new ArgumentException(string.Format("The property {0} is not an enum", name));
}
StringBuilder html = new StringBuilder();
foreach (Enum item in Enum.GetValues(type))
{
string id = string.Format("{0}_{1}", metaData.PropertyName, item);
StringBuilder innerHtml = new StringBuilder();
innerHtml.Append(helper.RadioButtonFor(expression, item, new { id = id }));
innerHtml.Append(helper.Label(id, item.ToDescription()));
TagBuilder div = new TagBuilder("div");
div.AddCssClass("radiobutton");
div.InnerHtml = innerHtml.ToString();
html.Append(div.ToString());
}
TagBuilder container = new TagBuilder("div");
container.AddCssClass("radiobutton-container");
container.InnerHtml = html.ToString();
return MvcHtmlString.Create(container.ToString());
}
}
Note, this uses the following extension method
public static string ToDescription(this Enum value)
{
FieldInfo field = value.GetType().GetField(value.ToString());
DescriptionAttribute[] attributes = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attributes.Length > 0)
{
return attributes[0].Description;
}
return value.ToString();
}
which allows you to decorate the enum values with a 'friendly' name
public enum SpaceType
{
Home,
[Description("2 bed apartment")]
Apartment,
....
}
and in the view
#Html.EnumRadioButtonListFor(m => m.Listing.SpaceType)
I have 3 entity classes; Team, TeamContact and TeamAddress.
Relationships
-Team one-to-one TeamContact
-TeamContact one-to-on TeamAddress
Create Method
[HttpPost]
public ActionResult Create(Team model)
{
if (ModelState.IsValid)
{
new Team
{
Name = model.Name,
Division = model.Division,
Description = model.Description,
TeamContact = new TeamContact
{
EmailAddress = model.TeamContact.EmailAddress,
PhoneNumber = model.TeamContact.PhoneNumber,
TeamAddress = new TeamAddress
{
Box = model.TeamContact.TeamAddress.Box,
StreetName = model.TeamContact.TeamAddress.StreetName,
StreetNumber = model.TeamContact.TeamAddress.StreetNumber,
City = model.TeamContact.TeamAddress.City,
PostalCode = model.TeamContact.TeamAddress.PostalCode,
Province = model.TeamContact.TeamAddress.Province
}
}
};
_dataSource.Save();
}
return View(model);
}
My problem is that when i try scaffolding a create view, only labels and fields of entity Team are scaffolding. The view is being strongly typed agains team entity, my guess is that this is where the source of my problem is. See below.
Create View
#model Soccer.Domain.Entities.Club.Team
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Team</legend>
<div class="editor-label">
#Html.LabelFor(model => model.Name)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Name)
#Html.ValidationMessageFor(model => model.Name)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Division)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Division)
#Html.ValidationMessageFor(model => model.Division)
</div>
<div class="editor-label">
#Html.LabelFor(model => model.Description)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.Description)
#Html.ValidationMessageFor(model => model.Description)
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
Team
namespace Soccer.Domain.Entities.Club
{
public class Team
{
//Holds players into a specific teams
[HiddenInput(DisplayValue = false)]
public virtual int Id { get; set; }
[Display(Name = "Full Name:")]
public virtual string Name { get; set; }
//Current playing division
[Display(Name = "Division:")]
public virtual string Division { get; set; }
[Display(Name = "About the team:")]
[DataType(DataType.MultilineText)]
public virtual string Description { get; set; }
public virtual TeamContact TeamContact { get; set; }
public virtual ICollection<Player> Players { get; set; }
}
}
TeamContact
namespace Soccer.Domain.Entities.Club
{
public class TeamContact
{
[Key]
[ForeignKey("Team")]
[HiddenInput(DisplayValue = false)]
public virtual int TeamId { get; set; }
[DataType(DataType.EmailAddress)]
[Display(Name = "Email:")]
public virtual string EmailAddress { get; set; }
[DataType(DataType.PhoneNumber)]
[Display(Name = "Phone:")]
public virtual string PhoneNumber { get; set; }
public virtual Team Team { get; set; }
public virtual TeamAddress TeamAddress { get; set; }
}
}
TeamAddress
namespace Soccer.Domain.Entities.Club
{
public class TeamAddress
{
//Team Mailing address
[Key]
[ForeignKey("TeamContact")]
[HiddenInput(DisplayValue = false)]
public virtual int TeamContactId { get; set; }
[Display(Name = "P.O.Box:")]
public virtual string Box { get; set; }
[Display(Name = "Street Name:")]
public virtual string StreetName { get; set; }
[Display(Name = "Street Number:")]
public virtual string StreetNumber { get; set; }
[Display(Name = "City:")]
public virtual string City { get; set; }
[Display(Name = "Postal Code:")]
public virtual string PostalCode { get; set; }
[Display(Name = "Province:")]
public virtual string Province { get; set; }
public virtual TeamContact TeamContact { get; set; }
}
}
What can i do to get passed this?
You can use an EditorTemplate in your view that will render out content within the context of the Team object, so that the model binder will work when you post your form
1) In the folder where your view currently is, create a sub-folder called 'EditorTemplates'
2) Create a new partial view in this folder, name it the same as the model you are trying to scaffold, e.g. TeamContact
3) Write your HTML in the new view for the TeamContact model
4) In your current view for Team, you can now do this...
#Html.EditorFor(model => model.TeamContact)
MVC will recognise that you have a custom template for this object type and will use your partial view to render the page.
When you look at the markup in the HTML page, you will see it renders controls as
Team.TeamContact.EmailAddress
...giving the TeamContact a context against the Team object.
Editor templates are excellent for this sort of thing, particularly if you have a collection of child objects - MVC will correctly index all of your items in the view
One additional thing, you should probably consider splitting out your 'entity domain' objects from what you are trying to render in the view. View Models are used for this, and allow you to keep your domain\data objects out of the presentation layer.