Passing a predefined Object from View to Controller by form in MVC6 - asp.net-core-mvc

Code in my controller:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult CreateRedBlood(Donor donor)
{
if (ModelState.IsValid)
{
//create
Blood newBlood = new Blood();
if(donor != null)
{
DateTime todaysdate = DateTime.Now;
newBlood = new Blood("RBC", donor.ID);
}
_context.Blood.Add(newBlood);
_context.SaveChanges();
Code in my View:
<form asp-action="CreateRedBlood" method="post">
<div class="form-horizontal">
<h4>Make Donation</h4>
<hr />
<div class="form-group">
<input type="submit" value="Make Red Blood Cell Donation"class="btn btn-default" />
</div>
</div>
</form>
Prior to the use of this form the page has got FullDonorDetails from the controller, and uses model.donor.x to get all the useful bits of information out.
What I'd like to do is pass model.donor back into this form, so that when the button is pressed it takes all that handy information and puts it straight back into CreateRedBlood.
Any ideas?
Thanks!
EDIT: Shyju asked for the following. This is the index controller I'm working with to get fullDonorDetails.
public IActionResult Index(string searchString)
{
FullDonorDetails fullDonorDetails = new FullDonorDetails();
//Get Donor
Donor emptyDonor = new Donor();
Donor activeDonor = new Donor();
if (!string.IsNullOrEmpty(searchString)
&& searchString.Length == 10)
{
activeDonor = _context.Donor.Single(m => m.NHN == searchString);
if (activeDonor != null)
{
fullDonorDetails.Donor = activeDonor;
}
else
{
fullDonorDetails.Donor = emptyDonor;
}
}
else
{
fullDonorDetails.Donor = emptyDonor;
}
//Get History
List<Blood> donorBloodHistory = new List<Blood>();
if (activeDonor != emptyDonor)
{
//RedBlood
var BloodHistory = from r in _context.Blood
select r;
BloodHistory = BloodHistory.Where(s => s.DonorId.Equals(activeDonor.ID));
foreach (Blood currentBlood in BloodHistory)
{
donorBloodHistory.Add(currentBlood);
}
List<Blood> sortedList = donorBloodHistory.OrderBy(o => o.DateTaken).ToList();
sortedList.Reverse();
fullDonorDetails.DonorHistory = sortedList;
}
return View(fullDonorDetails);
}

Since your HttpPost action method is reading only the ID property of the Donor class, which is a parameter of your HttpPost action method, you should keep that property value in a form field with the same name (ID).
#model FullDonorDetails
<form asp-action="CreateRedBlood">
<div class="form-horizontal">
<h4>Make Donation</h4>
<hr />
<input type="hidden" asp-for="Donor.ID" name="ID" />
<div class="form-group">
<input type="submit" value="Make RBC Donation"class="btn btn-default" />
</div>
</div>
</form>
Now when user submits the form, The param of your HttpPost action method will have the value of the Donor ID (which you set in your GET action).

Related

Forms inside foreach loop MVC

I have situation where MVC controller has sent list of records.
Those records are displayed in view in order that every single record is a form, so it can be posted record by record.
#model IList<FMS.Application.Models.TransferLineUpdateResponse>
#{
ViewData["Title"] = "Transfer Lines Page";
}
<div class="row">
<div class="col-12">
#foreach (var item in Model)
{
<form method="post" class="form-inline">
<div class="form-group">
<input type="hidden" asp-for="#item.Id" readonly class="form-control" />
<input type="hidden" asp-for="#item.TransferHeaderId" readonly class="form-control" />
</div>
<div class="form-group">
<label asp-for="#item.Item"></label>
<input asp-for="#item.Item" readonly class="form-control" />
</div>
<div class="form-group">
<label asp-for="#item.ToLocationId"></label>
<select class="form-control" asp-for="#item.ToLocationId" asp-items="ViewBag.ToLocations"></select>
</div>
<div class="form-group">
<input type="submit" asp-route-status="Accepted" class="btn btn-success" /> |
<input type="submit" asp-route-status="Rejected" class="btn btn-danger" />
</div>
</form>
}
</div>
</div>
When one of two buttons is clicked and form submission is called, as parameter in controller all my records like Id, ToLocationId are null or empty guids in case if property has type guid. Why it is not taken data which has been actually changed in view ?
Regards
P.S.here is the code of controller
[HttpGet("Transfer/Details/{id}")]
public async Task<IActionResult> Details(Guid id)
{
var lines = await _transferLineService.GetTransferLines(id);
var locations = await _locationService.GetLocations();
var customLocations = locations
.Where(w=>w.Code != "Tranzit")
.Select(s => new
{
Id = s.Id,
Description = $"{s.Code} - {s.Description}"
});
ViewBag.ToLocations = new SelectList(customLocations, "Id", "Description");
return View(lines);
}
[HttpPost("Transfer/Details/{transferHeaderId}")]
public async Task<IActionResult> AcceptDetails(Guid transferHeaderId, TransferLineUpdateResponse update)
{
var result = await _transferLineService.UpdateTransferLine(update);
await _transferHeaderService.UpdateTransferHeaderStatus(update.TransferHeaderId);
return RedirectToAction("Details",new { transferHeaderId = update.TransferHeaderId });
}
Why it is not taken data which has been actually changed in view ?
Model binding looks through the sources for the name pattern prefix.property_name. If nothing is found, it looks for just property_name without the prefix.In your code,the asp-for tag helper will generate the name like:item.propertyName.It could not match with backend model.You could use [Bind(Prefix ="item")] to specify the prefix.
Change like below:
[HttpPost("Transfer/Details/{transferHeaderId}")]
public async Task<IActionResult> AcceptDetails(Guid transferHeaderId,[Bind(Prefix ="item")] TransferLineUpdateResponse update)
{
//do your stuff...
//_context.Update(update);
//await _context.SaveChangesAsync();
//your get method used [HttpGet("Transfer/Details/{id}")]
//so,it should be id not transferHeaderId
return RedirectToAction("Details", new { id = update.TransferHeaderId });//also change here...
}
Result:

Passing Viewbag Data from View to Controller in ASP.Net MVC3 Razor

In my ASP.Net MVC3 Razor project i have to pass value from view to controller.The view contains one submit button that is used to pass selected image file and two other input data.This two input data is from a controller named "FileUpload"(ViewBag.Data1 = CusId;ViewBag.Data2 = Name;).When submitting the button i have to pass these three (Image,CusId,Name) to another controller to upload the image file.
Controller Code
public ActionResult FileUpload(int CusId, string Name)
{
ViewBag.Data1 = CusId;
ViewBag.Data2 = Name;
return View();
}
[HttpPost]
public ActionResult UploadPhoto(ElixiCustPro elixi, HttpPostedFileBase file)
{
//return null;
try
{
if (file != null && file.ContentLength > 0)
{
if ((file.ContentType == "image/jpeg") || (file.ContentType == "image/gif") || (file.ContentType == "image/png"))//check allow jpg, gif, png
{
elixi.Image = new byte[file.ContentLength];
file.InputStream.Read(elixi.Image, 0, file.ContentLength);
var filename = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/ElixirFiles/UploadImagesElixir/"), filename);
file.SaveAs(path);
ecp.Image = new byte[file.ContentLength];
ecp.ImageUrl = path;
ment.ElixiProData.Add(ecp);
ment.SaveChanges();
return RedirectToAction("ImageResult");
}
}
}
catch (Exception ex)
{
return View(ex.Message.ToString());
}
return View();
}
View Code
#using (Html.BeginForm("UploadPhoto", "Home", FormMethod.Post, new { #enctype = "multipart/form-data" }))
{
#* <div class="form-group">
<label class="col-lg-2 control-label">
Customer ID</label>
<div class="col-lg-10">#Html.TextBoxFor(model => model.CusId, new { #class = "form-control" })</div>
<label class="col-lg-2 control-label">
Customer Name</label>
<div class="col-lg-10">#Html.TextBoxFor(model => model.Name, new { #class = "form-control" })</div>
</div>*#
<input type="hidden" id="id" />
<div class="col-md-6">
<div class="form-group">
<label class="col-lg-2 control-label">
DMIT Image</label>
<div class="col-lg-10">
#ViewBag.Data1
#ViewBag.Data2
<input type="file" id="file" name="file">
<input type="submit" class="btn btn-success" value="Upload" />
</div>
</div>
</div>
}
ViewBag can't pass data back to controller. You should post those values back inside the form. Easiest thing would be to not to use ViewBag and add the data to model type.
Then you can pass them with hidden inputs using HTML helpers like this:
#Html.HiddenFor(item => item.CustomerId)
#Html.HiddenFor(item => item.ImageId)
If that's not possible, you can add the hidden inputs manually. Just keep in mind that the name attributes are important for model binding.
<input type="hidden" name="CustomerId" value="#ViewBag.Data1" />
Yes you cannot pass a Viewbag from view to controller.
But you can pass them using TempData.
Add this to your View.
#{TempData["Data1"]=ViewBag.Data1}
#{TempData["Data2"]=ViewBag.Data2}
But this TempData passes the information as an object.
So typecasting is necessary in your Controller.
int x=Convert.ToInt32(TempData["Data1"]);
string y=(TempData["Data2"]).ToString();
I tried,it is working.
or you can send TempData from Controller in get method,and use the same to pass from view to post method instead of Viewbag.

How to use hidden field values from view to controller in asp.net mvc 3

I have to pass hidden filed values to controller action. So I have tried in the following way, but I am getting null values.
I have tried both methods i.e formcollection and viewmodel concept
Controller
public ActionResult MapIcon()
{
Hidden hd = new Hidden();
return View(hd);
}
[HttpPost]
public ActionResult MapIcon(Hidden hidden)
{
var value=hidden.hiddevalue;//null
FormCollection col = new FormCollection();
var value = col["hidden1"];
// string value = mycontroler.ControlName;
return View(hidden);
}
View
#model SVGImageUpload.Models.Hidden
Razor view:#using (Html.BeginForm(new { id = "postform" }))
{
<input type="hidden" id="" value="7" name="hidden1" />
<input type="hidden" id="" value="7" name="hidden2"/>
<input type="submit" value="Match"/>
}
Viewmodel
public class Hidden
{
public string hiddevalue { get; set; }
}
Try this, In Razor view:
#using (Html.BeginForm(new { id = "postform" }))
{
#Html.HiddenFor(m=>m.hiddevalue)
<input type="submit" value="Match"/>
}
It seems to me like you are trying to get multiple values into the POST controller. In that case, and by your exam, the value from the hidden input is enough. In that case, you can setup your controller as so:
public ActionResult Index()
{
Hidden hd = new Hidden();
return View(hd);
}
[HttpPost]
public ActionResult Index(IEnumerable<string> hiddens)
{
foreach (var item in hiddens)
{
//do whatter with item
}
return View(new Hidden());
}
and as for your view, simple change it in order to bind to the same name "hiddens" as so:
#using (Html.BeginForm(new { id = "postform" }))
{
<input type="hidden" value="7" name="hiddens" />
<input type="hidden" value="2" name="hiddens" />
<input type="submit" value="Match" />
}
Hope this serves what you are looking forward to.
if your hidden value is static.Than try this
View
#using (Html.BeginForm(new { id = "postform" }))
{
#Html.HiddenFor(m=>m.hiddevalue)
<input type="hidden" id="" value="7" name="hidden1" />
<input type="hidden" id="" value="7" name="hidden2"/>
<input type="submit" value="Match"/>
}
Controller
[HttpPost]
public ActionResult MapIcon(Hidden hidden, string hidden1, string hidden2)
{
var hiddenvalue = hidden.hiddevalue;
var hiddenvalue1 = hidden1;
var hiddenvalue2 = hidden2;
var value=hidden.hiddevalue;//null
FormCollection col = new FormCollection();
var value = col["hidden1"];
// string value = mycontroler.ControlName;
return View(hidden);
}
Script
$(document).ready(function () {
$('#hiddevalue').val("Jaimin");
});

Pass image & data from view to controller

I want to pass image as well as some data from view to controller on submit button click.
Bellow is my code
My View
#using (Html.BeginForm("AccountPhotoPost", "Post", FormMethod.Post, new {enctype = "multipart/form-data", accountId = Model.accountId }))
{
<text>Post Photo : </text> <input type="file" name="file" id="file" />
<input type="submit" value="Post Photo" id="saveButton"/>
}
My controller action
[HttpPost]
public ActionResult AccountPhotoPost(HttpPostedFileBase file, long accountId)
{
}
Here problem is that as it is FormMethod.Post , data is not passed from view to controller & if I remove this then data is passed but image is not passed.
How can I send both together ?
Try this
#model SomeModel
#using (Html.BeginForm("AccountPhotoPost", "Post", FormMethod.Post, new {enctype = "multipart/form-data"}))
{
<text>Post Photo : </text> <input type="file" name="file" id="file" />
#Html.HiddenFor(model => model.accountId )
<input type="submit" value="Post Photo" id="saveButton"/>
}
in Controller
[HttpPost]
public ActionResult AccountPhotoPost(SomeModel model ,HttpPostedFileBase file)
{
var Id = model.accountId;
}
Try This
HttpPostedFileBase hpf = Request.Files["file"] as HttpPostedFileBase;
var httpPostedFileBase = Request.Files["file"];
if (httpPostedFileBase != null && (hpf != null && httpPostedFileBase.ContentLength > 0))
{
var postedFileBase = Request.Files["file"];
if (postedFileBase != null)
{
fileName = postedFileBase.FileName;
BinaryReader reader = new BinaryReader(postedFileBase.InputStream);
byte[] attachmentBinary = reader.ReadBytes((int)postedFileBase.ContentLength);
hcUserReview.AttachmentByteValue = attachmentBinary;
hcUserReview.FileName = fileName;
}
}

pass a value of the form from view to controller

how do i pass the value of the form, which is (i assume) a string of date to the controller...
here is my view:
<script type="text/javascript" language="javascript">
$(function () {
$(".datepicker").datepicker({ onSelect: function (dateText, inst) { $("FORM").submit(); },
altField: ".alternate"
});
});
</script>
#model IEnumerable<CorReservation.Models.Reservation>
#{
ViewBag.Title = "Index";
}
<div class="divRightSide">
<div>
<div class="datepicker">
</div>
<form action="/" title="fff">
<input type="text" class="alternate" readonly="readonly" />
</form>
</div>
// do something eg. foreach (var item in Model)
{ #Html.DisplayFor(modelItem => item.Date)}
here is my controller: i want to pass the date selected from the datepicker to the controller and then the controller would return an Ienumerable of reservations...
DateTime date = System.DateTime.Now;
private ReservationEntities db = new ReservationEntities();
public ViewResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(string dateInput)
{
date = Convert.ToDateTime(dateInput);
var reservations = db.Reservations.Where(r=> r.Date ==date).Include(r => r.Employee).Include(r => r.Room).OrderByDescending(r => r.Date);
return View(reservations);
}
There are 2 ways to do this. Make the form input name attribute match the expected attribute in your controller.
For example:
<input type="text" class="alternate" readonly="readonly" name="dateInput" />
Or if there's going to be a lot of input values, use a Model.
It's automatically done based on the 'name' attribute of the HTML fields you want to submit.
Change your form to
<form action="/" title="fff">
<input name="dateInput" type="text" class="alternate" readonly="readonly" />
</form>
And it should work just like that.
Also, as you are using Razor syntax, you could use the Razor HTML helpers like so
#model IEnumerable<CorReservation.Models.Reservation>
#{
ViewBag.Title = "Index";
}
<div class="divRightSide">
<div>
<div class="datepicker">
</div>
#using(#Html.BeginForm("<your controller name>", "<your action name e.g. Index>"){
Html.TextBox("dateInput", "", new { #readonly="readonly", #class="alternate" })
}
</div>
// do something eg. foreach (var item in Model)
{ #Html.DisplayFor(modelItem => item.Date)}

Resources