MVC Approve or Disapprove button - c#

Controller
[ActionName("Index")]
[HttpPost]
public ActionResult IndexPost(string button, int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
string buttonClicked = Request.Form["SubmitButton"];
if(buttonClicked == "Accept")
{
CurrentApplication currentApplication = db.CurrentApplications.Find(id);
currentApplication.AppStatus = "APPROVED";
db.SaveChanges();
}
else if(buttonClicked == "Decline")
{
CurrentApplication currentApplication = db.CurrentApplications.Find(id);
currentApplication.AppStatus = "UNAPPROVED";
db.SaveChanges();
}
//Save Record and Redirect
return RedirectToAction("Index");
}
Index View
<button type="submit" name="SubmitButton" value="Approve" class="btn btn-sm btn-success">Approve</button>
<button type="submit" name="SubmitButton" value="Unapprove" class="btn btn-sm btn-danger">Unapprove</button>
In my Index view, i have a table where there are rows of data i can "Approve" or "Disapprove" using 2 buttons. I tried using these http://www.scriptscoop.net/t/b7bd27aee268/c-asp-net-mvc-two-different-buttons-in-form-submit.html and ASP.NET MVC two different buttons in form submit. I want the status value to change to Approve or Disapprove when the user clicks the corresponding button. But I'm not sure why it isn't working as I tried to code it similarly to the Edit view.

You can get the value of the submit button as a parameter to your Action method, now all you have to do is compare its value inside the Action and perform the changes you need . In your view the value of the buttons are value="Approve" for the Approve button and value="Unapprove" for the Unapprove button whereas you are comparing it with "Accept" and "Decline".
[ActionName("Index")]
[HttpPost]
public ActionResult IndexPost(string SubmitButton, int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
string buttonClicked = SubmitButton;
if(buttonClicked == "Approve")
{
CurrentApplication currentApplication = db.CurrentApplications.Find(id);
currentApplication.AppStatus = "APPROVED";
db.SaveChanges();
}
else if(buttonClicked == "Unapprove")
{
CurrentApplication currentApplication = db.CurrentApplications.Find(id);
currentApplication.AppStatus = "UNAPPROVED";
db.SaveChanges();
}
//Save Record and Redirect
return RedirectToAction("Index");
}

In your HTML, the values for Approve and Unapprove buttons are Approve and Unapprove respectively. However, in your code, you are comparing buttonClicked with Accept and Decline.
It should be like this:
[ActionName("Index")]
[HttpPost]
public ActionResult IndexPost(string button, int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
string buttonClicked = Request.Form["SubmitButton"];
if(buttonClicked == "Approve") // value of Approve button
{
CurrentApplication currentApplication = db.CurrentApplications.Find(id);
currentApplication.AppStatus = "APPROVED";
db.SaveChanges();
}
else if(buttonClicked == "Unapprove") // value of Unapprove button
{
CurrentApplication currentApplication = db.CurrentApplications.Find(id);
currentApplication.AppStatus = "UNAPPROVED";
db.SaveChanges();
}
//Save Record and Redirect
return RedirectToAction("Index");
}

you can try this ;
Controller:
[ActionName("Index")]
[HttpPost]
public ActionResult IndexPost(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var result = Request.Form["result"];
CurrentApplication currentApplication = db.CurrentApplications.Find(id);
currentApplication.AppStatus = result;
db.SaveChanges();
//Save Record and Redirect
return RedirectToAction("Index");
}
View
<input type="hidden" name="result" id="result" />
<a data-value="Approve" class="btn btn-sm btn-success submitButton">Approve</a>
<a data-value="Unapprove" class="btn btn-sm btn-danger submitButton">Unapprove</a>
Javascript
<script>
$('.submitButton').on('click', function (e) {
e.preventDefault();
$('#result').val($(this).data('value'));
$('form').submit();
});
</script>

Related

How to upload file in database and display them in ASP.Net MVC 5

I am a beginner in ASP.Net MVC 5 and I want to know how to upload file in database and the display them to the user. I saw numerous example on internet related to above question. But all talks about putting file in some solution folder. But I want to upload file to database and be able to retrieve it in "Details View".
Issue: I am able to upload file in Database, but I am not sure how to Display the file link to user. Clicking on which user should be able to view/download the uploaded file. Below is my attempt.
Model:
public class File
{
public int Id { get; set; }
[StringLength(255)]
public string FileName { get; set; }
public byte[] Content { get; set; }
}
Controller:
// GET: FileUpload
public ActionResult Create()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(File file, HttpPostedFileBase upload)
{
try
{
if (ModelState.IsValid)
{
if (upload != null && upload.ContentLength > 0)
{
var tempfile = new File
{
FileName = System.IO.Path.GetFileName(upload.FileName),
};
using (var reader = new System.IO.BinaryReader(upload.InputStream))
{
tempfile.Content = reader.ReadBytes(upload.ContentLength);
}
file.Content = tempfile.Content;
}
_context.Files.Add(file);
_context.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.");
}
return View(file);
}
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
File f1 = _context.Files.Where(f => f.Id == id).SingleOrDefault();
if (f1 == null)
{
return HttpNotFound();
}
// NOT SURE WHAT TO HERE
return View(f1);
}
View: Details.chtml file
#model fileupload.Models.File
<h4>File</h4>
#* NOT SURE HOW TO HANDLE THE FILE LINK HERE*#
So, In the database I can see some binary content entry in "Content" Column. But I am not sure how can I display some link in the detail section. I want to display the file link in the details view. Clicking on which the file will get downloaded or something like preview. Kindly guide me.
EDIT 1
public FileContentResult Download(int id)
{
var file = _context.Files.First(f => f.Id == id);
var fileRes = new FileContentResult(file.Content.ToArray(), "application/pdf");
fileRes.FileDownloadName = file.FileName;
return fileRes;
}
Assuming your code in your controller is correctly populating your model, you simply need base64 encode the image and display that.
#{
var encodedImage = Convert.ToBase64String(Model.Content);
var embeddedImage = $"data:image/png;base64,{encodedImage}";
}
<img src="#embeddedImage" />
Take a look at this question as well: MVC How to display a byte array image from model
Add below code in model :
public string imagePath { get; set; }
[Display(Description = "imgfile")]
[RegularExpression(#"([a-zA-Z0-9()\s_\\.\-:!##$%^&])+(.png|.jpg|.gif|.bmp|.tiff|.PNG|.JPG|.GIF|.BMP|.TIFF)$", ErrorMessage = "Only Image files allowed.")]
public HttpPostedFileBase imgfile { get; set; }
In controller (This will validate your image for maore than 1mb from your action, if u want to validate it before post you can google it for jquery validations) :
if (userRegObj != null && userRegObj.imgfile != null && userRegObj.imgfile.FileName != null && userRegObj.imgfile.ContentLength > 1024000)//1 MB
{
TempData["msg"] = "danger~Profile Picture Should be Less Than 1 MB";
if (userRegObj.Id <= 0)
{
return View(userRegObj);
}
return RedirectToAction("Action", "Controller", new { id = userRegObj.Id });
}
else if (userRegObj != null && userRegObj.imgfile != null && userRegObj.imgfile.FileName != null)
{
string path = Path.Combine(Server.MapPath("~/Media/ProfilePics"), Path.GetFileName(userRegObj.imgfile.FileName)); // folder to save images
userRegObj.imagePath = Path.GetFileName(userRegObj.imgfile.FileName);
userRegObj.imgfile.SaveAs(path);
}
In view (This code will help you if your model having an image then it will show the image in the upload section else it will show a default image as you want to manage yourself) :
#if (Model != null && Model.Id>0 &&Model.imagePath!=null)
{
<div class="form-group">
<label for="exampleInputEmail1">Upload Your Image:<br /><small>(Width:155, Height:155)</small></label>
<span class="imageupld">
<img src="#Url.Content("~/Media/ProfilePics/"+Model.imagePath)" alt="obsequium" id="profilepic" style="margin-top:8.5px" />
</span>
<span class="file-up" style="overflow:hidden;">
<span class="pic" id="p">#Model.imagePath</span>
#Html.TextBoxFor(m => m.imgfile, new { #class = "profilepic", type = "file", data_value = "pic", tabindex = 17, accept = "image/*", id = "picVal", #onchange = "checkImage()" })
#Html.ValidationMessageFor(m => m.imgfile, "", new { #class = "text-red", id = "imgVal" })
</span>
</div>
}
else if (Model != null && Model.Id>0 && Model.imagePath == null )
{
<div class="form-group">
<label for="exampleInputEmail1">Upload Your Image:<br /><small>(Width:155, Height:155)</small></label>
<span class="imageupld">
<img src="#Url.Content("~/Content/Template/")images/imgupload.png" alt="obsequium" id="profilepic" style="margin-top:8.5px">
</span>
<span class="file-up" style="overflow:hidden;">
<span class="pic">Upload Image</span>
#Html.TextBoxFor(m => m.imgfile, new { #class = "profilepic", type = "file", data_value = "pic", tabindex = 17, accept = "image/*", id = "picVal", #onchange = "checkImage()" })
#Html.ValidationMessageFor(m => m.imgfile, "", new { #class = "text-red", id = "imgVal" })
</span>
</div>
}

How to fix System.NullReferenceException' occurred in App_Web_xxxx.dll in asp.net mvc?

This is a part of my view code for Index action of Manage Controller.
<div class="mngimg">
#using (Html.BeginForm("UploadPhoto", "Manage", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="btn btn-default browseimg">
<input type="file" name="file" id="files" onchange="this.form.submit()" />
</div>
<div class="btn btn-default browseimg">
#Html.ActionLink("Remove Photo", "RemovePhoto", "Manage")
</div>
}
</div>
</div>
}
</dd>
<dt>Password:</dt>
<dd>
[
#if (Model.HasPassword) <!-- Here is my error. The Model is null -->
{
#Html.ActionLink("Change your password", "ChangePassword")
}
else
{
#Html.ActionLink("Create", "SetPassword")
}
]
</dd>
Whenever I open this page and click "Remove Photo" I keep getting an error saying that An exception of type 'System.NullReferenceException' occurred in App_Web_ckoryptg.dll but was not handled in user code. I tried debugging, but I am unable to figure out why my Model.HasPassword is becoming null. Here is my RemovePhoto Action from Manage Controller.
[HttpPost]
public async Task<ActionResult> UploadPhoto(HttpPostedFileBase file)
{
if (file != null && file.ContentLength > 0)
{
var user = await GetCurrentUserAsync();
var userId = user.Id;
var fileExt = Path.GetExtension(file.FileName);
var fnm = userId + ".png";
if (fileExt.ToLower().EndsWith(".png") || fileExt.ToLower().EndsWith(".jpg") || fileExt.ToLower().EndsWith(".gif"))// Important for security if saving in webroot
{
var filePath = HostingEnvironment.MapPath("~/Content/Images/") + fnm;
var directory = new DirectoryInfo(HostingEnvironment.MapPath("~/Content/Images/"));
if (directory.Exists == false)
{
directory.Create();
}
ViewBag.FilePath = filePath.ToString();
file.SaveAs(filePath);
return RedirectToAction("Index", new { Message = ManageMessageId.PhotoUploadSuccess });
}
else
{
return RedirectToAction("Index", new { Message = ManageMessageId.FileExtensionError });
}
}
return RedirectToAction("Index", new { Message = ManageMessageId.Error });// PRG
}
private async Task<ApplicationUser> GetCurrentUserAsync()
{
return await UserManager.FindByIdAsync(User.Identity.GetUserId());
}
I opened a default MVC project that comes with visual studio and I added these extra things that I followed from this tutorial ASP.NET upload images. How do I resolve this?
Edit:
This is my RemovePhoto action.
public ActionResult RemovePhoto()
{
string file = "~/Content/Images/" + User.Identity.GetUserId() + ".png";
if(System.IO.File.Exists(Server.MapPath(file)))
System.IO.File.Delete(Server.MapPath(file));
return View("Index");
}
Just Redirect back to your Index action. That way you don't have to instantiate your Index model in your RemovePhoto action. Can read more about this pattern here.

Using TempData with returnview()

I have two ActionResults and I am trying to just simply pass an int id from one ActionResult to another. I attempted to use tempdata, but after looking at the value from the debugger the value was zero. The tempdata example I looked at used redirecttoaction(). Can this be done with returnview()?
public ActionResult Details(int? id)
{
myEMSurvey mySurvey = db.myEMSurveys.Find(id);
if (mySurvey == null)
{
return HttpNotFound();
}
SurveyViewModel svm = new SurveyViewModel();
svm.mySurvey = mySurvey;
svm.Questions = (from s in db.myEMSurveyQuestions
where s.SurveyID == id
select s).ToList();
svm.Options = (from o in db.myEMQuestionOptions
where o.SurveyID == id
select o).ToList();
svm.Anwsers = (from a in db.myEMSurveyAnswers
where a.SurveyID == id
select a).ToList();
int intid = id.Value;
TempData["ID"] = intid;
return View(svm);
}
[HttpPost]
public ActionResult CsvDownload()
{
int id = Convert.ToInt32(TempData["ID"]); //value of id=0, TempData["ID"] = 33
var Anwsers = (from a in db.myEMSurveyAnswers
where a.SurveyID == id
select a).ToList();
//id = 0
}
CsvDownload in Details view:
#using (Html.BeginForm("CsvDownload", "Survey", FormMethod.Post))
{
<div class="text-center">
<input type="submit" name="button" value="Download" class="btn btn-success" />
</div>
<br />}
The error in my code was the convert to int32.
Instead I needed to convert like so:
int id = (int)(TempData["ID"]);
This is known as "unboxing". It's a straight cast from object to int.

Searching with a dropdown list in asp.net MVC

I'm new to ASP.NET MVC. I want to use selected items from my dropdownlist to search my database table. The dropdownlist was generated from a BOL model which automatically binds to the view.
Below are my code snippet
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using BLL;
using BOL;
namespace DentiCareApp.Areas.Admin.Controllers
{
[AllowAnonymous]
public class GenerateInvoiceController : Controller
{
private TreatmentBs objBs;
public GenerateInvoiceController()
{
objBs = new TreatmentBs();
}
// GET: Admin/GenerateInvoice
public ActionResult Index(string CompanyID)
{
DentiCareEntities db = new DentiCareEntities();
ViewBag.CompanyId = new SelectList(db.Companies, "CompanyId", "CompanyName");
if (CompanyID == null)
{
return View();
}
else
{
return View(db.Treatments.Where(x => x.Company == CompanyID.Take(50)));
}
//return View();
}
Also below is the interface of view.
Secondly, I also want the search result to appear on the same page. How do I do this? If I create a separate action for this, I will need to create a separate view for it. Can partial view be used? If so how?
Below is the code to the View
#model BOL.GenerateInvoice
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<p></p>
<p></p>
<p></p>
<h2>Quickly Generate Invoice</h2>
#using (Html.BeginForm("Index", "GenerateInvoice", FormMethod.Get))
{
#Html.AntiForgeryToken()
<div class="">
<div>
#Html.DropDownList("MyCompany.CompanyId", (IEnumerable<SelectListItem>)ViewBag.CompanyId, "Select Company", new { #class = "form-control" })
#Html.ValidationMessageFor(model => model.MyCompany.CompanyId, "", new { #class = "text-danger" })
<input type="submit" value="Search" class="btn btn-primary" />
</div>
</div>
}
Try this.
Controller action:
public ActionResult Index(string CompanyID)
{
DentiCareEntities db = new DentiCareEntities();
ViewBag.CompanyId = new SelectList(db.Companies, "CompanyId", "CompanyName", CompanyID); // preselect item in selectlist by CompanyID param
if (!String.IsNullOrWhiteSpace(CompanyID))
{
return View();
}
return View(db.Treatments.Where(x => x.CompanyID == CompanyID).Take(50));
}
View code:
#model IEnumerable<Treatment>
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Quickly Generate Invoice</h2>
#using (Html.BeginForm("Index", "GenerateInvoice", FormMethod.Get))
{
#Html.AntiForgeryToken()
#Html.DropDownList("CompanyId", (SelectList)ViewBag.CompanyId, "Select Company", new { #class = "form-control" })
<input type="submit" value="Search" class="btn btn-primary" />
}
#if(Model != null && Model.Any())
{
foreach(var item in Model)
{
#Html.DisplayFor(model => item)
}
}
You can change the DisplayFor() here to show individual properties of the given Treatment, such as #Html.DisplayFor(model => model.TreatmentID) and such
The Above code worked for me but with little tweaks. Here are few modification I made to your code.
The parameter in the Index Action was changed from string to integer.
The Optional Parameter in the ViewBag.CompanyId was removed.
Lastly, the line if (!String.IsNullOrWhiteSpace(CompanyID)) and changed to if (CompanyID == 0) { return View(treatmentList);}
The result however is great as it worked like a charm! Thanks for your help!
// GET: Admin/ListTreatment
public ActionResult Index(string sortOrder, string sortBy, string Page, int CompanyID = 0)
{
ViewBag.sortOrder = sortOrder;
ViewBag.sortBy = sortBy;
var treatmentList = objBs.GetALL();
//ViewBag.employeeCompany = employeeCompany.Distinct();
switch (sortOrder)
{
case "Asc":
treatmentList = treatmentList.OrderBy(x => x.TreatmentDate).ToList();
break;
case "Desc":
treatmentList = treatmentList.OrderByDescending(x => x.TreatmentDate).ToList();
break;
default:
break;
}
ViewBag.CompanyId = new SelectList(db.Companies, "CompanyId", "CompanyName");
ViewBag.TotalPages = Math.Ceiling(objBs.GetALL().Where(x=>x.CompanyId > 0).Count()/10.0);
int page = int.Parse(Page == null ? "1" : Page);
ViewBag.Page = page;
treatmentList = treatmentList.Skip((page - 1) * 10).Take(10);
if (CompanyID == 0)
{
return View(treatmentList);
}
return View(db.Treatments.Where(x => x.CompanyId == CompanyID).Take(50));
}
First : for entity framework id should be nullable, so it can be accepted as argument, the action parameter should be int? CompanyID
Second : the comparison is not correct with (CompanyID == 0)
It should be (CompanyID == null)

Pass dropdown lselected item back to controller

I am trying to pass the selected item in a dropdown list back to the controller to fire a stored procedure.
Controller that populates the list:
public ActionResult Activate()
{
var query = db.Certificates
.Where(a => a.Active == "Y")
.Select(cer => cer.CertificateNumber.Substring(0, 4))
.Distinct()
.OrderBy(cer => cer);
ViewBag.BoxNumber = new SelectList(query.ToList());
return View();
}
View I want tet the value from.
#{
ViewBag.Title = "Activate";
}
<h2>#ViewBag.Title.</h2>
<h3>#ViewBag.Message</h3>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.DropDownList("BoxNumber", String.Empty)
<input type="submit" value="Activate" class="btn btn-default" />
}
Action I want to use it in:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Activate(string BoxNumber)
{
var connection = new SqlConnection(ConfigurationManager.ConnectionStrings["GrandCelebration"].ConnectionString);
var command = new SqlCommand("ActivateCertificates", connection);
command.CommandType = CommandType.StoredProcedure;
command.Parameters.AddWithValue("#BoxNumber", BoxNumber);
connection.Open();
command.ExecuteNonQuery();
connection.Close();
return RedirectToAction("Activate");
}
The selected item is not being returned.

Categories