Pass ID from URL to Database is going null - c#

My view looks like this
My url link http://localhost:63897/UploadImages?id=1361. 1361 is my pr_id. I need to pass the id which is 1361 from url to database, but it is going null.
Here is my controller code:
public ActionResult UploadImages(int id) {
ViewBag.prid = id;
return View();
}
[HttpPost]
public ActionResult UploadImages([Bind(Include = "id,photo_url,photo_caption,photo_credit,pr_id")] Photo photos, HttpPostedFileBase photo_file)
{
if (ModelState.IsValid)
{
if (photo_file != null && photo_file.FileName != null && photo_file.FileName != "")
{
try
{
string path = Path.Combine(Server.MapPath("~/Images/Releases"), Path.GetFileName(photo_file.FileName));
photo_file.SaveAs(path);
string f1 = path.Substring(path.LastIndexOf("\\"));
string[] split = f1.Split('\\');
string newpath = split[1];
string imagepath = "~/Images/Releases/" + newpath;
photos.photo_url = imagepath;
_db.Photos.Add(photos);
_db.SaveChanges();
}
catch (Exception ex)
{
ViewBag.Message = "ERROR:" + ex.Message.ToString();
}
return RedirectToAction("List");
}
}
return View();
}
View :
#Html.HiddenFor(model => model.pr_id, new { #Value = ViewBag.id })

Your view bag dictionary item's key is prid. But in your view code you are using a different key.
Use ViewBag.prid. Also use the Hidden helper method.
#Html.Hidden("pr_id", new { #value = ViewBag.prid })
Or just write plain HTML and set the value attribute value.
<input type="hidden" name="pr_id" value="#ViewBag.prid" />
Check the view source of the page to confirm the correct value attribute is set to the hidden input element with name pr_id
Assuming you fixed the wrong ViewBag key name, your existing approach will basically generate the below markup
<input Value="23" name="pr_id" type="hidden" value="0" />
Remember, Value != value
This is one major reason i do not use dynamic stuff like ViewBag. You make a silly mistake like this and there are no warnings/errorrs from the IDE/compiler. It just silently fails :( If you use a strongly typed view model, the compiler will complain when you make a silly typo.
Also do not use the *For method and try to manually overwrite the value/id/name etc. The helpers are designed to set the value/name/id attribute values properly. Consider using a view model and use these For methods with them. That will be less code.
If your view model has a property called pr_id, set that property value in your GET action, send that view model to the view and in the view(which is strongly typed to this view model), simply call HiddenFor method on that property
#Html.HiddenFor(a=>a.pr_id);

Related

.Net Core - Passing Input Controller value into ViewComponent/Controller Action

I am pretty sure if this was in a form I could simply just put
var name = this.Request.Form["txtName"];
To get the value in the action. But since its not a form I am just trying to get this value of a hidden input in my controller so I can use it in the method.
I have tried passing in the name of the input in the action parameters using a session/tempdata but that does not work because in a new tab it then uses this same value so I have to have a set value saved on the page and use that value in the controller.
I thought I could do a querystring but also I have not had luck passing this into the action.
Here is what I have.
Html
<input id="txthguid" name="txthguid" type="hidden" value="#TempData["guid"]" />
<input asp-for="TabGuid" type="hidden" value="#TempData["guid"]" />
#await Component.InvokeAsync("DataPage", Model)
View Compnent
public async Task<IViewComponentResult> InvokeAsync(string sessionID, object txthguid, LNPartVM model)
{
if (TempData != null)
{
TempData.Keep();
}
List<LNPartVM> lstData = null;
try
{
_logger.LogInformation(txthguid.ToString());
_logger.LogInformation(TempData["guid"].ToString());
var jsonResponse = "";
//string sessionID = _contextAccessor.HttpContext.Session.Id;
//string sessionID = _contextAccessor.HttpContext.Session.GetString("sGUID");
var tabGuid = Request.Query["txthguid"];
_logger.LogInformation(tabGuid);

Display a collection of images after each upload MVC

Have gone through the first 3 pages of Google and still can't get to the bottom of this. I have a controller which I am using to upload images:
[HttpPost]
[Authorize(Roles = "Admin,Tradesman,Customer")]
public ActionResult UploadFile(HttpPostedFileBase file)
{
// to do: ensure only valid file types are sent
try
{
if (file.ContentLength > 0)
{
using (var ctx = new ApplicationDbContext())
{
if (ModelState.IsValid)
{
// Need to check we have a current UserId and JobId before we go any furthur
var profileData = Session["UserProfile"] as UserProfileSessionData;
if (profileData.JobIdGuid.ToString().Length != 36)
{
// to do: something went horribly wrong! Redirect back to main view
}
if (profileData.UserIdGuid.ToString().Length != 36)
{
// to do: something went horribly wrong! Redirect back to main view
}
var photo = new Photos();
photo.Guid = Guid.NewGuid();
photo.Url = Server.MapPath("~/Images/2017");
photo.Extension = Path.GetExtension(file.FileName);
photo.JobGuid = profileData.JobIdGuid;
photo.UserIdGuid = profileData.UserIdGuid;
photo.Timestamp = DateTime.Now;
ctx.Photo.Add(photo);
ctx.SaveChanges();
string _path = Path.Combine(photo.Url, photo.Guid.ToString() + photo.Extension);
file.SaveAs(_path);
}
}
}
ViewBag.Message = "File Uploaded Successfully.";
return View();
}
catch
{
ViewBag.Message = "File upload failed.";
return View();
}
}
Each image is saved to a given location, the location saved to the db, happy days. Want I want though is for my images to be displayed on the same page after each upload. The model is as you'd expect just Id, Guid, Url, Extension, UserId, Timestamp.
Here is the view that uploads the images:
#{
ViewBag.Title = "UploadFile";
}
<h2>Upload File</h2>
#using (Html.BeginForm("UploadFile", "Job", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
#Html.TextBox("file", "", new { type = "file" }) 
<br />
<input type="submit" value="Next" />
#ViewBag.Message
</div>  
// to do display the images uploaded
}
Is it possible to just have some kind of for...each and have each displayed at the bottom? Anyone know how to do this! Btw this is my first C# MVC app so if this is daft question I apologise. Thanks in advance :)
You should be following the P-R-G pattern. After successfully saving the data in your HttpPost action method, you should do a redirect to your GET action method, where you will read the data you need and pass it to the view where you will display it.
I would create a view model to represent each image and use that
public class ProfileImageVm
{
public string FileName { set;get;}
public DateTime CreatedTime { set;get;}
}
Now, for your save partin your http post action method, i would advise you to not save the physical location of the file in the table. The Server.MapPath returns the physical path. Storing that is unnecessary. What if you decide to move the location to some other directory in the server tomorrow? You could simply store the unique fileName. Let's assume that you want to store all the files in the Images/2017 in app root ,you can use Server.MapPath to get the physical location so that you can store the file in disk, but do not use that to store your table record.
var fileName = Path.GetFileNameWithoutExtension(file.FileName);
photo.Url = fileName ;
photo.Extension = Path.GetExtension(file.FileName);
With this code, it is simply storing the file name(without extension) as it is, not a unique name. That means, if you are uploading a second file with same name, it will overwrite the first one in disk. If you want to generate a unique file name, use the GetUniqueName method from this post.
Now in the GET action method, you read the Photos collection and create a list of our view model from that.
public ActionResult UploadFile()
{
var list= ctx.Photos
.Select(x=>new ProfileImageVm { FileName=x.Url + x.Extension ,
CreatedTime = x.Timestamp })
.ToList();
return View(list);
}
Now in your UploadFile view will be strongly typed to a list of ProfileImageVm, you can loop through the model data and render the images.
#model List<ProfileImageVm>
#using (Html.BeginForm("UploadFile", "Job", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{
#Html.TextBox("file", "", new { type = "file" })
<input type="submit" value="Next" />
}
<h3>Images</h3>
#foreach(var item in Model)
{
<img src="~/Images/2017/#item.FileName" />
<p>Uploaded at #item.CreatedTime </p>
}
Now, after successfully saving the photo and the record in table, you will return a redirect response to the GET action.
file.SaveAs(_path);
return RedirectToAction("Upload","Job");
You can also keep the base path ~/Images/2017 in a config settings/constant and use that across your app so if you ever decide to change it to ~/Images/profilepics, there is only one place you have to change.

MVC - Can I set a model attribute in the view and get the value form a script?

This is the Controller that returns the above-mentioned view:
public PartialViewResult Day()
{
Day model = new Day();
return PartialView("_Day", model);
}
[HttpPost]
public PartialViewResult Day(Day model)
{
return PartialView("_Day", model);
}
I wrote both the Get and the Post method after I read this question. Note that I haven't set the model in the Controller.
Then I have my View:
#model Timing.Models.Day
#{
Timing.Models.Day d = new Timing.Models.Day();
d.UserId = "some value";
}
This piece of code is working fine: when I go to retrieve, or display, d.UserId I get the right value.
Furthermore I have a script in the same view.
<script>
function getUserId() {
//some code that gets a string
return userId;
}
</script>
And also this script is working right.
I looked for a solution and this is the best I've been able to find:
#{
Timing.Models.Day d = new Timing.Models.Day();
d.UserId = Page.ClientScript.RegisterStartupScript(this.GetType(), "Getuser", "getUserId()", true);
}
But it's not working because of something that is null (I wasn't able to understand what was null though).
Is there a way to solve this problem?
For those who ask, I'm using a script because the value I want to set is the one of an html element (this is my related question).
Thanks!
Declare your variable you want in javascript
#{
var useridForjs = model.property // access model and set useridForjs
}
to use in javascript
<script>
function getUserId() {
//some code that gets a string
var myserversidevarvalue = '#useridForjs'; // here myserversidevarvalue will store value..
return userId;
}
</script>
Make it easy on yourself and inject your id into a hidden form field, easily obtainable by javascript. Add this to your view:
Html.HiddenFor(model.userId)
Then access it like this:
function getUserId() {
return $('#userId').val();
}

how to catch id in aspx page in MVC

I'm working on a MVC production project.
In my Production details view I have some buttons to get some more data from the database, but for this I need the id of the Product. I can see it exist but can I catch it?
Here's my controller that return data:
public ActionResult Details(long AProductionOrderId)
{
ProductionOrderList item = new ProductionOrderList();
item = ProductionOrderReg.GetProductionOrders(conn, AProductionOrderId);
ViewData["item"] = item;
return View();
}
Here's my details page when it load, I can see the id, but how to catch and use it in the buttons in the left to bring more date ?
You could use a hidden input on your view page to submit the ID.
your View:
<form method="post">
<button type="submit">Button Text</button>
<input type="hidden" name="AProductionOrderId" value="#ViewData['item']">
</form>
i wrote this im my controller
ViewData["id"] = AProductionOrderId;
and catched it in my view
long id = Convert.ToInt64( ViewData["id"]);
If you controller is:
public ActionResult Details(long AProductionOrderId)
{
var item = ProductionOrderReg.GetProductionOrders(conn, AProductionOrderId);
ViewBag.ProductionOrderId = AProductionOrderId;
return View(item);
}
then your AProductionOrderId will be in the ViewBag although I don't see the reason why you need it since whatever the type of item is (single object instance or list of objects) it contains your ID as a property because you're fetching the item by this ID. Anyway in your model you then need to declare your model like this:
#model YourModelNamespace.ProductionOrderList
and now you can access any property of your model in your view. But if you really want you can access it via ViewBag like this:
#{
long AProductionOrderId = Viewbag.AProductionOrderId;
}

ViewData coming up as null

I have this test page. This is the action method.
public ActionResult TestView()
{
ViewData["Test"] = "1";
return View("TestView");
}
In TestView.cshtml, I have this line of code
#ViewData["Test"]
It is coming up as null, it is not printing the "1".
Any idea what I am doing wrong?
Thanks.
MV3 have ViewBag as a new object that can hold the dynamic properties as Key/Value pair.
So you can directly assign a property using ViewBag. For e.g. -
In your action in controller you can write something like
ViewBag.Message = "1";
Now to retrieve the value you can write in your .cshtml
<h2>#ViewBag.Message</h2>

Categories

Resources