MVC Pass value/parameter from controller to View - c#

what i'm trying to achieve:
1. fill up form
2. save into database
3. redirect user to another view that displays some details (referenceID)
so here's what i have
controller:
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(ClearanceViewModel myViewModel, TClearance clearance, TRefsNum referenceNo)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var stringChars = new char[8];
var random = new Random();
for (int i = 0; i < stringChars.Length; i++)
{
stringChars[i] = chars[random.Next(chars.Length)];
}
var finalString = new String(stringChars);
string refNo = DateTime.Now.Year + finalString;
items.RefNum = refNo;
db.TClearances.Add(items);
db.SaveChanges();
return RedirectToAction(items.RefNum, "displayRef");
}
code above does save to database whatever user has input then redirect to view "displayRef" and items.refNum is the value that i'm trying to pass to view
view:
#model RDMSPNPOnlineClearance.Models.TClearance
#{
var getRef = Model.RefNum;
}
this is your ref number: #Html.LabelFor(model => model.RefNum, htmlAttributes: new { #class = "control-label" })
code above, is trying to get the expected value "items.refNum" and use the value to display it to the user.
so what actually happening is, user fill ups, saves to db, then redirected to "displayRef" view. no problem in saving part. the problem is im not getting the refNum in the displayRef view. the url changes to something like:
Localhost:55433/items.refNum/view
so, how do i pass that value to be displayed to the user?

Do you need RedirectToAction? Can you not just return the view...
return View("displayRef", items.RefNum);
If you have to use RedirectToAction, this means you're redirecting to a controller action and you must specify it like so...
return RedirectToAction("Action","controller", new {#id=id});
Also your model in the view is incorrect, you're binding a string refNo, but at the top of your view stating that you want to bind a class RDMSPNPOnlineClearance.Models.TClearance

Related

Html.ValidationMessage won't show error in view

I am trying to add error on my own using ModelState.AddModelError, and when I try to display it on view, validation span is in html, but there is no message.
Controller
if (!paymentTypeId.HasValue || !shipmentTypeId.HasValue)
{
var model = new CheckoutViewModel()
{
ShipmentTypes = m_ShipmentTypeService.GetAllShipmentTypes(true),
PaymentTypes = m_PaymentTypeService.GetAllPaymentTypes(true),
};
SetBaseProperties(model, null);
ModelState.AddModelError("ErrorCheckout", "L_CHOOSE_TYPE_ERROR");
return View(model);
}
View
#Html.ValidationMessage("ErrorCheckout", new { #class = "text-danger" })
On other pages I did same and it worket, I don't know what is problem here
Problem was in sending request to Action via ajax. When I changed to Html.Form and placed submit, it started working, strange behavior, but here you go.

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.

How to pass Parameter from gridview to controller using SetDataItemTemplateContent in mvc4 devExpress by clicking Edit Button?

Hi i have one registration page and it contain fields called UID,UserName,Password. I am using dev Express gridview. When i click the edit button it need to pass the particular row key value to controller but it passing null parameter to controller. Now what i want is i want to pass the particular row key Parameter to controller by clicking edit button in grid view in mvc dev express gridview using SetDataItemTemplateContent.Below i post my code please any one correct my code and tell me what mistake i did.
My Model (UserMasterViewModel)
public int UID{get;set;}
public string UserName{get;set;}
public string Password{get;set;}
My Controller Code
Public ActionResult UserMasterEdit(int? id)
{
View_MUsrRegistration userregistrartion = db.MUsrRegistration.Find(id)
UserMasterViewModel usermasterviewmodel = new UserMasterViewModel();
usermasterviewmodel.UserName = userregistrartion.UserName;
usermasterviewmodel.Password = userregistrartion.Password;
return View(usermasterviewmodel)
}
Grid View Code
#Html.DevExpress().GridView(
settings =>
{
settings.Name = "gvEditing";
settings.KeyFieldName = "UID";
settings.CallbackRouteValues = new { Controller = "UserMaster", Action = "UserMasterPartial" };
settings.Width = Unit.Percentage(100);
settings.Columns.Add(column => {
column.Caption = "#";
column.SetDataItemTemplateContent(c =>
{
ViewContext.Writer.Write(
Html.ActionLink("Edit", "UserMasterEdit", new { UID = DataBinder.Eval(c.DataItem, "UID") }) + " " +
Html.ActionLink("Delete", "UserMasterDelete", new { ProductID = DataBinder.Eval(c.DataItem, "UID") },
new { onclick = "return confirm('Do you really want to delete this record?')" })
);
});
column.Settings.AllowDragDrop = DefaultBoolean.False;
column.Settings.AllowSort = DefaultBoolean.False;
column.Width = 70;
});
settings.Columns.Add("UserName");
settings.Columns.Add("Password");
settings.ClientLayout = (s, e) =>
{
if(e.LayoutMode == ClientLayoutMode.Loading) {
if(Session["GridState"] != null)
e.LayoutData = (string)Session["GridState"];
}
else
Session["GridState"] = e.LayoutData;
};
}).Bind(Model).GetHtml()
EDIT View
#model MSSERP.Models.UserMasterViewModel
#{
Html.EnableClientValidation();
}
#using(Html.BeginForm("UserMaterUpdate", "UserMaster", FormMethod.Post, new { #class = "edit_form" })) {
#Html.HiddenFor(m=>m.UID)
<div class="line">
#Html.Label(UserNmae)
#Html.TextBoxFor(m=>m.UserName)
</div>
<div class="line">
#Html.Label(Password)
#Html.TextBoxFor(m=>m.Password)
</div>
<div class ="line">
<input type="submit" value ="Save"/>
</div>
In this i am clicking edit button it passing the null value to controller. I tried many ways but cant able to pass the UID parameter to controller.
i donno what mistake i did in this action. I tried my level best to explain this issue Any one understand and help me to resolve this issue.
Thanks..
Try the following'
Change:
Html.ActionLink("Edit", "UserMasterEdit", new { UID = DataBinder.Eval(c.DataItem, "UID") })
To:
Html.ActionLink("Edit", "UserMasterEdit", new { id = DataBinder.Eval(c.DataItem, "UID") }, null)
The parameter name should match the controller's parameter name.
The added null argument is needed to ensure that the right parsing method is called. see this link:HTML.ActionLink method
In the GridView where your DisplayFor's are located:
<a class="ml-2" href="/Merchant/Merchant_Boarding/#Html.DisplayFor(modelItem => item.GUID)" title="Edit">Edit</a>
Or use an ActionLink:
#Html.ActionLink("Edit", "Merchant_Boarding", new { id = (item.GUID) }, new { #class = "ml-2" })
In your Get:
[HttpGet]
public IActionResult Merchant_Boarding(string? id)
{
var model = new MerchantDetail();
MerchantData merchdata = new MerchantData();
model = merchdata.RetrieveMerchantData(id);
merchdata.Dispose();
return View(model);
}
The id variable will contain the value you passed in from the grid view. From there, you can populate your model and show it.

How to retain parameters for xtraReport with a dataset as the datasource

I have a devExpress xtraReport that is being supplied by a strongly typed dataset. As long as I'm hard coding two parameters into the Actions, it loads the data into the dataset and displays in the report. Once I try to make it pass the values from the main page down through the partial, it fails. My first attempt was to pass the parameters through the ViewBag, wasn't working, so switched to a model, still not working right.
main page controller
public ActionResult SubsequentVisitReport(int noteType = 1, int noteId = 9)
{
ViewBag.noteType = noteType;
ViewBag.noteId = noteId;
ReportParameters reportParamters = new ReportParameters();
reportParamters.noteType = noteType;
reportParamters.noteId = noteId;
return View(reportParamters);
}
main page cshtml - added in the EditorFor to make sure the model makes it there (it does). Have tried calling the Partial both with and without putting 'Model'
#model ReportParameters
#Html.EditorFor(m => m.noteId)
#Html.EditorFor(m => m.noteType)
#Html.HiddenFor(m => m.id)
#Html.HiddenFor(m => m.noteType)
#Html.HiddenFor(m => m.noteId)
#Html.Partial("_SubsequentVisitReport", Model)
controller for the partial - this does not receive the data from the model and I don't understand why. The model is NOT null, all the values are 0 (zero).
[HttpPost]
public ActionResult _SubsequentVisitReport(ReportParameters model)
{
int noteType = model.noteType;
int noteId = model.noteId;
rptSubsequentVisit report = new rptSubsequentVisit();
try { report.DataSource = getSubsequentVisitData(model.noteType, model.noteId).Tables[0]; }
catch { return RedirectToAction("Not_Authorized"); }
ViewData["Report"] = report;
return PartialView("_SubsequentVisitReport");
}
The view for the partial
#model ReportParameters
#Html.HiddenFor(m => m.id)
#Html.HiddenFor(m => m.noteType)
#Html.HiddenFor(m => m.noteId)
#Html.DevExpress().DocumentViewer(settings =>
{
// The following settings are required for a Report Viewer.
settings.Name = "reportViewer1";
settings.Report = (rptSubsequentVisit)ViewData["Report"];
// Callback and export route values specify corresponding controllers and their actions.
// These settings are required as well.
settings.CallbackRouteValues = new { Controller = "Reports", Action = "_SubsequentVisitReport"};
settings.ExportRouteValues = new { Controller = "Reports", Action = "_SubsequentVisitReportExport" };
}).GetHtml()
The data needs to persist through the partial both to load the note for viewing, but also for the export function.
What am I doing wrong, or is there another better way to do this?
Thanks,
Dave K.
The settings.CallbackRouteValues object tells the DocumentViewer where to request the actual report, and it can take parameters. Unfortunately it will be a separate request, so you can't send your model, only simple values that can be passed as strings. In this example, they are using a custom model for the report, but the model has to be re-created from raw values in each action.
If you convert your partial action to take integer parameters:
public ActionResult _SubsequentVisitReport(int noteType, int noteId)
you should be able to tack those arguments on the end of the CallbackRouteValues:
settings.CallbackRouteValues = new { Controller = "Reports",
Action = "_SubsequentVisitReport",
noteType = model.noteType,
noteId = model.noteId};

Passing action and controller values from view to another partialview

I have multiple index views with a different grid in each of these views, but all of them uses the same popup control. I dont want to make a partial view foreach index view that i have. So i put the popup partial view in the Shared folder.
But i have a Html.BeginForm('Action','Controller') in the popup partialview, and these values are different in each grid. How can i pass these from the view of the grid to the partial view of the popup?
The Grid View:
//Code Resumed
#Html.DevExpress().GridView(
settings =>
{
settings.Name = "TestMasterGrid";
settings.Column.Add("Id");
settings.Column.Add("Name");
settings.Column.Add("Email");
//Command Column Wich calls the popup control
}
The PopUp PartialView:
//Code resumed
using (Html.BeginForm("ActionINeedToGetFromTheGridView", "ControllerINeedToGetFromTheGridView", FormMethod.Post))
{
Html.DevExpress().TextBox(
textBoxSettings =>
{
textBoxSettings.Name = "reason";
textBoxSettings.ControlStyle.CssClass = "editor";
})
.Render();
Html.DevExpress().Label(
labelSettings =>
{
labelSettings.Name = "sh";
labelSettings.ControlStyle.CssClass = "label";
}).Render();
Html.DevExpress().Button(
buttonSettings =>
{
buttonSettings.Name = "btnUpdate";
buttonSettings.ControlStyle.CssClass = "button";
buttonSettings.Width = 80;
buttonSettings.Text = "OK";
buttonSettings.UseSubmitBehavior = true;
}
)
.Render();
Thanks!
Pass the action and controller names to the action that returns the PartialViewResult. Then, pass the names to the partial's model and use them in the BeginForm statement:
Html.BeginForm(Model.Action, Model.Controller, FormMethod.Post)
Edit:
I'm not very familiar with DevExpress, but I found the CallbackRouteValues member in settings. I'll use that for my example:
settings.CallbackRouteValues = new { Controller = "ControllerName", Action = "GetPartialView", desiredAction = "DesiredAction", desiredController = "DesiredController" }
In your controller, you'd have the action and controller parameters:
public PartialViewResult GetParialView(string desiredAction, string desiredController) {
var viewModel = new PartialViewModel { Action = desiredAction, Controller = desiredController);
Return PartialView("Name", viewModel);
}
I typed out this code by hand, so it's probably full of errors. Hopefully it gets the idea across, though.
Quick edit: changed some parameter names to make it a little clearer.

Categories

Resources