Reputation: 41
I have this model with required properties. Yes they are required for creating an item, but when I want to update a single column of them, I get this error about required fields. So it seems that my controller wants to update all of them.
In this case there's an item for sale and one can make an offer for it.
Part of my model:
public class Ad
{
public int AdID { get; set; }
[Required()]
[Display(Name = "Otsikko")]
public string Title { get; set; }
[Required()]
[DataType(DataType.MultilineText)]
[AllowHtml]
[Display(Name = "Kuvaus")]
public string Text { get; set; }
[Required()]
[DataType(DataType.Currency)]
[Display(Name = "Hinta")]
public float Price { get; set; }
[DataType(DataType.Currency)]
[Display(Name = "Tarjottu")]
public float Offer { get; set; }
My controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Offer([Bind(Include = "Offer")] Ad ad)
{
if (ModelState.IsValid)
{
db.Entry(ad).State = EntityState.Modified;
db.SaveChanges();
return RedirectToRoute("ilmoitus", new { id = ad.AdID });
}
else
{
var message = string.Join(" | ", ModelState.Values
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage));
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
}
}
Part of view:
@using (Html.BeginForm("Offer", "Ads"))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.AdID)
@Html.EditorFor(model => model.Offer, new { htmlAttributes = new { @class = "form-control offer-input", @placeholder = "Tarjoa..." } })
<button class="btn-default btn offer-btn">Tarjoa {{offer}} €</button>
}
I've tried this with same error How to Update only single field using EF
Upvotes: 2
Views: 75
Reputation: 33
I have two solution for the above query.
You can use two different models for updating and insertion example
Remove the properties from ModelState then TryUpdateModel
public ActionResult UpdateAd(Ad ad)
{
ModelState.Remove("Title");
ModelState.Remove("Text");
ModelState.Remove("Price");
var p = GetAd();
if (TryUpdateModel(p))
{
//Save Changes;
}
}
Upvotes: 0
Reputation: 41
I got it working like this, included all the other properties as hidden and bound them in the controller:
View:
@using (Html.BeginForm("Offer", "Ads"))
{
@Html.AntiForgeryToken()
@Html.HiddenFor(model => model.AdID)
@Html.HiddenFor(model => model.Title)
@Html.HiddenFor(model => model.Text)
@Html.HiddenFor(model => model.Price)
@Html.HiddenFor(model => model.Location)
@Html.HiddenFor(model => model.PaymentOptions)
@Html.HiddenFor(model => model.DeliveryOptions)
@Html.HiddenFor(model => model.SellerEmail)
@Html.EditorFor(model => model.Offer, new { htmlAttributes = new { @class = "form-control offer-input", @placeholder = "Tarjoa..." } })
<button class="btn-default btn offer-btn">Tarjoa {{offer}} €</button>
}
Controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Offer([Bind(Include = "AdID,Title,Text,Price,Offer,Location,PaymentOptions,DeliveryOptions,SellerEmail")] Ad ad)
{
if (ModelState.IsValid)
{
db.Entry(ad).State = EntityState.Modified;
db.SaveChanges();
return RedirectToRoute("ilmoitus", new { id = ad.AdID });
}
else
{
var message = string.Join(" | ", ModelState.Values
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage));
return new HttpStatusCodeResult(HttpStatusCode.BadRequest, message);
}
}
Is this a security issue though?
Upvotes: 1