Image not saving when updated in view - c#

While developing an ASP.NET MVC 4 application I ran into a problem updating a saved image.
Basically when the user selects the edit tab, their re-directed to the content they previously entered.
One such item of that content is an image, and when in the edit menu they can choose to replace the existing image.
I have the other content updating correctly but the image remains the same, when I place a breakpoint on the "edit" ActionResult, it show the image value for the passing model as null? newsArticle.ArticleImage = Null
FYI - Image is saved as a byte array.
Am I missing something ?
Controller....
[HttpPost]
public ActionResult Edit(NewsArticle newsArticle, int id, HttpPostedFileBase Article)
{
try
{
if (ModelState.IsValid)
{
NewsArticle savedArticle= _newsArticle.Get(id);
savedArticle.Body = newsArticle.Body;
savedArticle.Title = newsArticle.Title;
if (newsArticle.ArticleImage == null)
{
newsArticle.ArticleImage = savedArticle.ArticleImage;
}
else
{
using (var binaryReader = new BinaryReader(Request.Files[0].InputStream))
{
newsArticle.ArticleImage = binaryReader.ReadBytes(Request.Files[0].ContentLength);
}
savedArticle.ArticleImage = newsArticle.ArticleImage;
}
if (newsArticle.ImageName == null)
{
newsArticle.ImageName = savedArticle.ImageName;
}
else
{
string imgeName = Path.GetFileName(Article.FileName);
savedArticle.ImageName = imgeName;
}
_uow.SaveChanges();
return RedirectToAction("Index");
}
}
catch (System.Data.DataException)
{
//Log th error(add a variable name after DataExpection)
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
}
return View(newsArticle);
}
View..........
#using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype = "multipart/form-data", #class = "form-horizontal", id = "newsEditForm" }))
{
#Html.ValidationSummary()
#Html.HiddenFor(model => model.ID)
<div class="control-group">
<label class="control-label">Posted on :</label>
<div class="controls">
<span class="text">#Model.DateCreated.Value.ToShortDateString()</span>
#*#Html.LabelFor(n => n.DateCreated)*#
</div>
</div>
<div class="control-group">
<label class="control-label">#Html.LabelFor(n => n.Title)</label>
<div class="controls">
#Html.TextBoxFor(n => n.Title, new { #class = "span4 m-wrap", rows = 1 })
</div>
</div>
<div class="control-group">
<label class="control-label">#Html.LabelFor(n => n.Body)</label>
<div class="controls">
#Html.TextAreaFor(n => n.Body, new { #class = "span12 ckeditor m-wrap", rows = 4 })
</div>
</div>
<div class="control-group">
<label class="controls">#Html.DisplayTextFor(model => model.ImageName)</label>
<div class="span4 blog-img blog-tag-data">
<div class="editor-field">
<input type="file" name="Article" id="ArticleImage" />
</div>
</div>
</div>
<div class="form-actions">
<button type="submit" class="btn green" id="submitnews"><i class="icon-ok"></i>Submit</button>
#Html.ActionLink("Cancel", "ArticleList", "Admin", null, new { #class = "btn blue" })
#*<button type="button" class="btn blue" onclick="location.href='ArticleList','Admin'">Cancel</button>*#
</div>
}

Related

How would I return a viewModel from a form on a view to the Controller

my model looks like this:
Bank Other LawFirm
| | |
BankContact OtherContact LawFirmContact
|______________|________________|
|
|
Contact
So when creating a contact I am trying to pass the information to create entry for the specific associated entity. At the moment I pass through a RelationId and ContactId and then try and create a the new entity in the controller but my "Save button on the form is not firing. I think it could be because I am not binding the information properly. I'm also posting this to see if this is the correct way to deal with a situation like this
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Save(ContactFormViewModel viewModel)
{
if (!ModelState.IsValid)
{
return View("ContactForm", viewModel);
}
if (viewModel.Contact.Id == 0)
{
_context.Contacts.Add(viewModel.Contact);
if (viewModel.IsBank)
{
var bankContact = new BankContact()
{
BankId = viewModel.RelationId,
Bank = _context.Banks.Single(b => b.Id == viewModel.RelationId),
ContactId = viewModel.ContactId,
Contact = viewModel.Contact
};
_context.BankContacts.Add(bankContact);
}
else if (viewModel.IsLawFirm)
{
var lawFirmContact = new LawFirmContact()
{
LawFirmId = viewModel.RelationId,
LawFirm = _context.LawFirms.Single(l => l.Id == viewModel.RelationId),
ContactId = viewModel.ContactId,
Contact = viewModel.Contact,
};
_context.LawFirmContacts.Add(lawFirmContact);
}
else if (viewModel.IsOther)
{
var standaloneContact = new StandaloneContact()
{
StandAloneId = viewModel.RelationId,
Standalone = _context.Standalones.Single(s => s.Id == viewModel.RelationId),
Contact = viewModel.Contact,
ContactId = viewModel.ContactId
};
_context.StandaloneContacts.Add(standaloneContact);
}
}
else
{
var contactInDb = _context.Contacts.Single(c => c.Id == viewModel.Contact.Id);
contactInDb.Firstname = viewModel.Contact.Firstname;
contactInDb.Surname = viewModel.Contact.Surname;
contactInDb.Email = viewModel.Contact.Email;
contactInDb.ContactNo = viewModel.Contact.ContactNo;
if (!String.IsNullOrWhiteSpace(viewModel.Contact.AltContactNo))
contactInDb.AltContactNo = viewModel.Contact.AltContactNo;
}
_context.SaveChanges();
return RedirectToAction("Index", "Contacts");
}
<div class="card">
<div class="card-body">
#using (Html.BeginForm("Save", "Contacts"))
{
<div class="form-row">
<div class="col-3">
<div class="form-group">
#Html.LabelFor(c => c.Contact.Firstname, new { #class = "form-control-label" })
#Html.TextBoxFor(c => c.Contact.Firstname, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.Contact.Firstname)
</div>
</div>
<div class="col-3">
<div class="form-group">
#Html.LabelFor(c => c.Contact.Surname, new { #class = "form-control-label" })
#Html.TextBoxFor(c => c.Contact.Surname, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.Contact.Surname)
</div>
</div>
</div>
<div class="form-row">
<div class="col-3">
<div class="form-group">
#Html.LabelFor(c => c.Contact.Email, new { #class = "form-control-label" })
#Html.TextBoxFor(c => c.Contact.Email, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.Contact.Email)
</div>
</div>
<div class="col-3">
<div class="form-group">
#Html.LabelFor(c => c.Contact.Birthday, new { #class = "form-control-label" })
#Html.TextBoxFor(c => c.Contact.Birthday, new { #class = "form-control datepicker-here", #data_language = "en", #autocomplete = "off" })
</div>
</div>
</div>
<div class="form-row">
<div class="col-3">
<div class="form-group">
#Html.LabelFor(c => c.Contact.ContactNo, new { #class = "form-control-label" })
#Html.TextBoxFor(c => c.Contact.ContactNo, new { #class = "form-control" })
#Html.ValidationMessageFor(c => c.Contact.ContactNo)
</div>
</div>
<div class="col-3">
<div class="form-group">
#Html.LabelFor(c => c.Contact.AltContactNo, new { #class = "form-control-label" })
#Html.TextBoxFor(c => c.Contact.AltContactNo, new { #class = "form-control" })
</div>
</div>
</div>
<div class="form-row">
<div class="col-4">
<div class="form-group">
<input type="radio" name="choice-contact-type" id="choice-contact-type-bank" required>
<label for="choice-contact-type-bank">Bank</label>
<div class="reveal-if-active">
#Html.DropDownListFor(b => b.BankContact.BankId, new SelectList(Model.Banks, "Id", "Name "), "", new { #class = "form-control" })
#{Model.IsBank = true;}
</div>
</div>
</div>
<div class="col-4">
<div class="form-group">
<input type="radio" name="choice-contact-type" id="choice-contact-type-lawFirm">
<label for="choice-contact-type-lawFirm">Law Firm</label>
<div class="reveal-if-active">
#Html.DropDownListFor(l => l.LawFirmContact.Id, new SelectList(Model.LawFirms, "Id", "Name"), "", new { #class = "form-control" })
#{Model.IsLawFirm = true;}
</div>
</div>
</div>
<div class="col-4">
<div class="form-group">
<input type="radio" name="choice-contact-type" id="choice-contact-type-standalone">
<label for="choice-contact-type-standalone">Other</label>
<div class="reveal-if-active">
#Html.DropDownListFor(s => s.StandaloneContact.Id, new SelectList(Model.Standalones, "Id", "Name"), "", new { #class = "form-control" })
#{Model.IsOther = true;}
</div>
</div>
</div>
</div>
#Html.AntiForgeryToken()
<button type="submit" class="btn btn-primary">Save</button>
}
</div>
</div>
Edit
The hidden dropdown fields are required and therefore validation is not allowing it to go through and because they were hidden I could not see that! The field is required because under my StandaloneContact Id is required. It is always required, so how would I get around this? setting it to a default value?
I'd still like to know if this is the best way to link a model to 3 different models with a many-to-many relationship. Is there another way to do this in MVC?
Try adding this to the form
#using (Html.BeginForm("Save", "Contacts", FormMethod.Post))
Also in regards to the correct way to send data from the view to the controller, it's mostly just what you need at the given time. If you simply want to send data in a form, this is probably the best way. However, if you, for example, what to send this data and then refresh a certain aspect of the page such as a partial view, I would suggest using ajax.
EDIT: Based on the edit to the question, by making the Standalone Contact ID a nullable, this should resolve the issue of the id always being required

How to handle multiple submit button and check boxes in c# MVC Entity Framework?

I have a page where i am displaying image, id, name and address. I have added checkbox and multiple submit buttons to delete update or add new records.
But when I click on any submit buttons i am getting unhandled exception error. (for example I have selected a checkbox and clicked delete button my control is going to Mycontroller from view and to the delete switch case. It is deleting the record but again when it is coming back to view I am getting the NullReferenceException.)
View :
#using (Html.BeginForm("MyAction", "MyController", FormMethod.Post))
{
#if (Model.Count> 0) // .NullReferenceException
{
#foreach (var MyDB in Model)
{
<div class="col-md-2">
<img src="#Url.Content(photos.photo_url)" style="width:100px; height:100px;" />
</div>
Html.LabelFor(model => MyDB.ID, new
{
#class = "control-label col-md-2"
})
<div class="col-md-2">
#Html.EditorFor(model => MyDB.ID)
#Html.ValidationMessageFor(model => MyDB.ID)
</div>
#Html.LabelFor(model => MyDB.name, new
{
#class = "control-label col-md-2"
})
<div class="col-md-2">
#Html.EditorFor(model => MyDB.name)
#Html.ValidationMessageFor(model => MyDB.name)
</div>
#Html.LabelFor(model => MyDB.address, new
{
#class = "control-label col-md-2"
})
<div class="col-md-2">
#Html.EditorFor(model => MyDB.address)
#Html.ValidationMessageFor(model => MyDB.address)
</div>
<div class="col-md-1">
input type="checkbox" class="checkboxes" value="#MyDB.id" name="id" />
</div>
}
}
}
<div class="col-md-offset-2 col-md-10">
<input type="submit" name="submitButton" value="UPDATE" />
<input type="submit" name="submitButton" value="ADD" />
<input type="submit" name="submitButton" value="DELETE" />
</div>
Controller :
public ActionResult MyController(IEnumerable<int> id, string submitButton)
{
switch (submitButton)
{
case "DELETE":
foreach (var item in id)
{
var delete = _db.MyDB.FirstOrDefault(s => s.id == item);
if (delete != null)
{
_db.MyDB.Remove(delete);
}
}
break;
case "ADD":
if (!ModelState.IsValid)
{
return RedirectToAction("ADDRecordPage", new
{
id
});
}
if (id == null)
{
return RedirectToAction("ADDRecordPage", new
{
id
});
}
break;
case "UPDATE" :
ViewBag.Message = "UPDATE";
break;
}
_db.SaveChanges();
ViewBag.Message = "Saved";
return View();
}
I found out what mistake I did. Inside controller i added return View(); it was returning null. so changed to return RedirectToAction("MyAction", new { id }); instead of return View();

Authorization: users able to edit their own details when loggedin

I have an application where I want Volunteers to be able to help with a Ceremony.
I would like them to be log in and click a button, this brings them to a page where their details appear and a list of Ceremonies they can apply for. I have that page working but I have no way of getting the current user logged in.
Also, for clarification: I have a Volunteer entity which holds the data and then a separate user entity. The username for a Volunteer is the same as their user entity.
I want to:
Compare the Username to the Volunteer Username and get the
VolunteerId.
2.This will then be used to edit/join a ceremony for that particular volunteer.
Here's my Volunteer Controller methods:
// GET:
public ActionResult VolunteerCeremony(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
string userName = string.Empty;
var getVolunteerId = (from u in db.Volunteers
where WebSecurity.CurrentUserName == u.Username
select u.VolunteerId).SingleOrDefault();
Volunteer v = (Volunteer)(from k in db.Volunteers
where getVolunteerId == k.VolunteerId
select k).SingleOrDefault();
if (v == null)
{
return HttpNotFound();
}
PopulateAssignedCeremonyData(v);
return View(v);
}
// GET:
public ActionResult VolunteerHub()
{
return View();
}
// POST: /Player/VolunteerCeremony/5
// To protect from overposting attacks, please enable the specific properties you want to bind to, for
// more details see http://go.microsoft.com/fwlink/?LinkId=317598.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult VolunteerCeremony(int? id, string[] selectedOptions)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var getVolunteerId = (from u in db.Volunteers
where WebSecurity.CurrentUserName == u.Username
select u.VolunteerId).SingleOrDefault();
var v = (Volunteer)(from k in db.Volunteers
where getVolunteerId == k.VolunteerId
select k).SingleOrDefault();
try
{
UpdateVolunteerCeremonies(selectedOptions, v);
db.Entry(v).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
catch (RetryLimitExceededException /* dex */)
{
//Log the error (uncomment dex variable name and add a line here to write a log.
ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists, see your system administrator.");
}
PopulateAssignedCeremonyData(v);
return View(v);
}
And then my Razor pages, the first which I want the user to click a link to bring them to the edit/join ceremony page:
#model PIMS.Entities.Volunteer
#{
ViewBag.Title = "VolunteerHub";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<li>#Html.ActionLink("Join Ceremony", "VolunteerCeremony", "Volunteers", null, new { id = #model.VolunteerId })</li>
This gives me an error on the new { id = #model.VolunteerId }
Then the page which I want to get to:
#model PIMS.Entities.Volunteer
#using Microsoft.AspNet.Identity
#{
ViewBag.Title = "VolunteerCeremony";
}
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<h2>Apply for Ceremony</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<hr />
#Html.ValidationSummary(true)
#Html.HiddenFor(model => model.VolunteerId)
<div class="form-group">
#Html.LabelFor(model => model.Name, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.Name, new { #readonly = "readonly" })
#Html.ValidationMessageFor(model => model.Name)
</div>
</div>
<div class="form-group">
#Html.LabelFor(model => model.VolunteerRole, "Volunteer Role", new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.VolunteerRole, new { #readonly = "readonly" })
#Html.ValidationMessageFor(model => model.VolunteerRole)
</div>
</div>
</div>
<div class="row">
<div class="col-md-2"> </div>
<div class="form-group col-md-4">
<label class="control-label">Assigned Ceremonies</label>
#Html.ListBox("selectedOptions", (MultiSelectList)ViewBag.SelectedCeremonies, new { #class = "form-control" })
</div>
<div class="form-group col-md-1" style="text-align:center">
<div class="form-group">
<button type="button" id="btnRight" class="btn btn-warning btn-lg">
<span class="glyphicon glyphicon-arrow-right"></span>
</button>
</div>
<div class="form-group">
<button type="button" id="btnLeft" class="btn btn-success btn-lg">
<span class="glyphicon glyphicon-arrow-left"></span>
</button>
<div></div>
</div>
</div>
<div class="form-group col-md-4">
<label class="control-label">Available Ceremonies</label>
#Html.ListBox("availOptions", (MultiSelectList)ViewBag.AvailCeremonies, new { #class = "form-control" })
</div>
<input type="submit" id="btnSubmit" value="Save" class="btn btn-default" />
</div>
<div style="text-align:center;">
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
#Scripts.Render("~/bundles/multisel")
}
Does anyone have any experience with this as it sort of key to my application!
in mvc there is something called session variables, its just like app.config variables, you declare them like this in the controller
Session["Volunteer"] = "volunteer1";
once declared they will remain declared for the entire session.
then you write code for the logoff to reset the Session variable to something that your code handles as no-one logged in or just null.

remove items to a bound list model in ASP MVC.NET

I followed an online tutorial to dynamically add items to a bound list model using ajax, which works perfectly. (http://www.mattlunn.me.uk/blog/2014/08/how-to-dynamically-via-ajax-add-new-items-to-a-bound-list-model-in-asp-mvc-net/comment-page-2/#comment-68909)
My question is, how would I correctly remove items from the list?
Right now what I have done is add a delete link which when clicked removes the item from the view. However, when I submit the form I noticed that the modelState is no longer valid and it has null entries for the item that was removed from the view. So I guess the model is not being updated.
Test.cshtml
#model TesterManager.Models.Test
<div class="form-group">
#Html.LabelFor(model => model.Software, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
<div class="form-group">
<div class="col-md-5">
#Html.DropDownListFor(m => m.Software, TesterManager.Models.Helper.GetTestSoftwares(), "Choose a USB Card", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.Software, "", new { #class = "text-danger" })
</div>
<div class="col-md-5">
#Html.EditorFor(model => model.Version, new { htmlAttributes = new { #class = "form-control", #title = "Enter a USB FW Version", #placeholder = "Enter a USB FW Version" } })
#Html.ValidationMessageFor(model => model.Version, "", new { #class = "text-danger" })
</div>
<div class="col-md-2">
Delete
</div>
</div>
</div>
</div>
AdminTesterConfigurations.cshtml (snippet):
#model TesterManager.Models.AdminTesterConfigurations
<div class="form-group">
<div class="col-md-6">
....
</div>
</div>
<hr />
<div class="form-group">
<div class="col-md-12">
<h3>Test Software</h3>
<div id="test-list">
#Html.EditorForMany(x => x.Tests, x => x.Index)
</div>
<input type="button" id="add-test" value="Add" />
</div>
</div>
RequestEditViewModel.cshtml:
#model TesterManager.Models.RequestEditViewModel
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
#Html.EditorFor(model => model.ShippingLocation)
#Html.EditorFor(model => model.RequesterTesterConfigurations)
#Html.EditorFor(model => model.AdminTesterConfigurations)
<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>
Edit.cshtml:
#model TesterManager.Models.RequestEditViewModel
#Styles.Render("~/Content/Edit")
#{
ViewBag.Title = "Edit";
Layout = "~/Views/Shared/_Layout.cshtml";
}
#section Scripts
{
<script>
jQuery(document).ready(function ($) {
$('#add-test').on('click', function () {
jQuery.get('/TesterManager/Request/AddTest').done(function (html) {
$('#test-list').append(html);
});
});
});
</script>
}
#using (Html.BeginForm())
{
<h2>Edit</h2>
#Html.AntiForgeryToken()
#Html.EditorFor(x => x);
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
RequestController.cs
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(RequestEditViewModel request)
{
if (ModelState.IsValid)
{
Request domainRequest = new Request(request);
requests.Add(domainRequest);
return RedirectToAction("Index");
}
return View(request);
}
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")]
public ActionResult AddTest()
{
var request = new RequestEditViewModel();
request.AdminTesterConfigurations.Tests.Add(new Test());
return View(request);
}
I realized that the problem was that when I would remove the item from the list in the view, I was not removing the hidden input for the collection indexer as well. I updated the code to remove the hidden input and it works fine now.

load another View page only on button click on the same page in mvc3

Below is my View page in which I have called action PromotionalMis and below this view code I have written my action
#using (Html.BeginForm("PromotionalMis", "Home", FormMethod.Post))
{
<div class="loginn" style="width:600px;">
<div class="logintext" style="width:154px;">
#Html.LabelFor(model => model.SongId, "Song Name")
</div>
<div class="mistype">
<select id="ddlsongs" name="ddlsongs" class="state" required="required">
</select>
</div>
</div>
<div class="loginn" style="width:600px;">
<div class="logintext" style="width:154px;">
</div>
<div class="generate">
<input type="submit" name="button" value="Generate" id="btn"/>
</div>
</div>
}
Below is my Action in Home Controller. I want to do things is that whenever I select albumname and song name from dropdownlist and when I will click on button My PromotionalMis view page should be visiblee on the same page
[HttpPost]
public ActionResult PromotionalMis(string ddlsongs)
{
if (Session["user"] != null && Session["user"].ToString() == "MISADMIN")
{
if (ddlsongs != "0")
{
string sSongName = "";
int iId = Convert.ToInt32(ddlsongs);
List<CRBT_Promotion> ss = new List<CRBT_Promotion>();
using (crbt_onwebEntities dbcontext = new crbt_onwebEntities())
{
ss = (from z in dbcontext.CRBT_Promotion where z.id == iId select z).ToList();
}
foreach (var ssname in ss)
{
sSongName = ssname.SongName.ToString();
}
Session["ss"] = sSongName;
ViewBag.songformis = sSongName;
}
return PartialView("PromotionalMis");
}
else
{
return RedirectToAction("LogOn");
}
}
#using (Ajax.BeginForm("ActionName", "Home", new AjaxOptions {HttpMethod="POST", UpdateTargetId = "filesBody" ,InsertionMode = InsertionMode.Replace}))
{
<div class="loginn" style="width:600px;">
<div class="logintext" style="width:154px;">
#Html.LabelFor(model => model.SongId, "Song Name")
</div>
<div class="mistype">
<select id="ddlsongs" name="ddlsongs" class="state" required="required">
</select>
</div>
</div>
<div class="loginn" style="width:600px;">
<div class="logintext" style="width:154px;">
</div>
<div class="generate">
<input type="submit" name="button" value="Generate" id="btnclick"/>
</div>
</div>
}
<div id="filesBody"></div
its working well

Categories