Hello everyone I would like to ask how to send data from view to controller ? I would like to describe my question with my controller and view as you can see below
Here is the login action controller
[HttpPost]
public ActionResult Login(Panel model, string Username, string Password, string CaptchaValue, string InvisibleCaptchaValue)
{
bool cv = CaptchaController.IsValidCaptchaValue(CaptchaValue.ToUpper());
bool icv = InvisibleCaptchaValue == "";
if (!cv || !icv)
{
ModelState.AddModelError(string.Empty, "The Captcha Code you entered is invalid.");
}
if (ModelState.IsValid)
{
if (model.Username == Username && model.Password == Password)
{
FormsAuthentication.SetAuthCookie(model.Username, false);
return RedirectToAction("index", "Home");
}
else
{
ModelState.AddModelError("", "Check your name or password");
}
}
return View();
}
So when user login, redirect to Home/index view. At this point everything is okey.
Here is my index view:
[Authorize]
public ActionResult index()
{
return View();
}
My question is how can I hold user's password parameter and send from index view to different controller to use this parameter in controller method but how ? For example I would like to use password parameter at my index_test controller method in where clause but first of all I need to send this data from index.
public ActionResult index_test()
{
return View(db.contents.Where(x => x.test_parameter== password).ToList());
}
You have to add a parameter to your action method:
public ActionResult index_test(string password) { ...
In Your view you can either send data to the action via a standard link:
#Html.ActionLink("Click me", "index_test", "Controller",
new { password = "StringOrVariable")
Or by doing a form post:
#using(Html.BeginForm("index_test")) {
<input type="hidden" name="password" value="mypassword" />
add some fields
<input type="submit" value="Send" />
}
In your view post the form back to the controller, for example
<form action = "yourcontroller/youraction" method = "POST" enctype = "multiparrt/form-data">
Related
I am having an issue with my Request.IsAuthenticated always return false. I am setting the AuthCookie
CurrentRequest currentRequest = null;
if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
} else if (login.ValidateUser(acct.UserName, acct.Password))
{
FormsAuthentication.SetAuthCookie(acct.UserName, true); //Edit on 11/12 #11:08
currentRequest = new CurrentRequest();
SessionWrapper.currentRequest = currentRequest;
return RedirectToAction("About", "Home");
}
//This is a partial login page that is supposed to display login or Logoff.
#using KMSS.Helper;
// this is always false
#if (Request.IsAuthenticated) //Same issue with User.Identity.IsAuthenticated
{
if (SessionWrapper.currentRequest != null)
{
<text> Welcome <strong> #SessionWrapper.currentRequest.Username </strong>
[#Html.ActionLink("Sign Off", "Logoff", "Account")]
</text>
} else {
#: [ #Html.ActionLink("Sign In", "Login", "Account") ]
}
} else
{
#:[ #Html.ActionLink("Sign In", "Login", "Account") ]
}
After reading online, I created a class with a bool value and tries to use that class instead. However, I am getting the object is not set to instance of a new variable exception.
Here is how I had it set up:
//Partial Login page
#model KMSS.Helper.ViewModelAuthenticate;
// this is always false
#if (Model.IsAuthenticated)
//The model is null even though I create create a reference in the Login Method i.e.
(ViewModelAuthenticate auth = new ViewModelAuthenticate();
{
if (SessionWrapper.currentRequest != null)
{
<text> Welcome <strong> #SessionWrapper.currentRequest.Username </strong>
[#Html.ActionLink("Sign Off", "Logoff", "Account")]
</text>
} else {
#: [ #Html.ActionLink("Sign In", "Login", "Account") ]
}
} else
{
#:[ #Html.ActionLink("Sign In", "Login", "Account") ]
}
//Here is the class
public class ViewModelAuthenticate
{
public bool IsAuthenticate { get; set; }
}
//Here is where I am initializing the class in the controller
public ActionResult Login()
{
ViewModelAuthenticate auth = new ViewModelAuthenticate();
auth.IsAuthenticate = false;
return View();
}
//I tried this inside and outside of Login, and it is called before the partial login view. However, I am still getting the object is not set to instance of a new variable exception.
What am I doing wrong here? Your help will be appreciated.
//Showing the authentication section of the config file.
<authentication mode="Forms">
<forms loginUrl="~/Account/Login" timeout="2880" slidingExpiration="true" />
</authentication>
I replaced my authentication section with this sample that a sample that I found here. It is working now.
Looking at your code, I feel that there is more going on here than you are showing us. Specifically, the variables CurrentRequest and SessionWrapper, setting them to null on the beginning of the Action method call, etc. I would suggest trying a basic, bare bones example in your project and then begin to add items back in as needed. No AJAX, only full page post back to the server from your login form. Such an example would look like:
Login View Model
public class LoginViewModel{
[Required]
public string UserName {get;set;}
[Required]
public string Password {get;set;}
}
Login POST Action method
[HttpPost]
public ActionResult Login(LoginViewModel model, string returnUrl){
if(!ModelState.IsValid){
return View();
}
if(!provider.ValidateUser(model.UserName, model.Password){
ModelState.AddModelError("", "The username/password combination does not match");
return View();
}
FormAuthentication.SetAuthCookie(model.UserName, true);
if(!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl){
return Redirect(returnUrl);
}
return RedirectToAction("About", "Home");
}
About View
#if(Request.IsAuthenticated){
<b>It WORKS!!</b>
}else{
<b>Nope, still not working</b>
}
I was testing and I set my time back a few days. For someone reason it caused this issue after putting the date back it was fine. I assume windows forms had the old date (which was todays date) cached so I assume it was expired. Just a thought about the matter.
I need to use Post-Redirect-Get to show data, which I entered in "Information" page on "Index" page. I have the following methods, but it doesn't work. It doesn't even redirect me on submit. What am I doing wrong?
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult About()
{
return View();
}
public ActionResult Information()
{
return View();
}
//Get info
[HttpGet]
public ActionResult Submit(Models.Information FirstName,
Models.Information LastName,
Models.Information DateOfBirth,
Models.Information HourOfBirth,
Models.Information NumberOfKids,
Models.Information Emso,
Models.Information Email,
Models.Information PlaceOfBirth)
{
if (ModelState.IsValid)
{
Models.Information info = new Models.Information();
info.FirstName = FirstName.ToString();
info.LastName = LastName.ToString();
info.DateOfBirth = Convert.ToDateTime(DateOfBirth);
info.HourOfBirth = Convert.ToDateTime(HourOfBirth);
info.NumberOfKids = Convert.ToInt32(NumberOfKids);
info.Emso = Emso.ToString();
info.Email = Email.ToString();
info.PlaceOfBirth = PlaceOfBirth.ToString();
TempData["info"] = info;
return RedirectToAction("Summary");
}
return View();
}
//Show info
[HttpPost]
public ActionResult Post(Models.Information info)
{
info.FirstName = ViewData["FirstName"].ToString();
info.LastName = ViewData["LastName"].ToString();
info.DateOfBirth = Convert.ToDateTime(ViewData["DateOfBirth"]);
info.HourOfBirth = Convert.ToDateTime(ViewData["HourOfBirth"]);
info.NumberOfKids = Convert.ToInt32(ViewData["NumberOfKids"]);
info.Emso = ViewData["Emso"].ToString();
info.Email = ViewData["Email"].ToString();
info.PlaceOfBirth = ViewData["PlaceOfBirth"].ToString();
return View();
}
}
I try to show data on Index page like this:
First name: <input type='text' runat="server" value="#ViewData["FirstName"]" /><br />
Your code looks sort of confusing to me and I am not sure what you are trying to accomplish. But first, let's use an example on what I think you are trying to accomplish.
User enters information on the information action/view
(POST)This is POSTed to a controller/action which then verifies the model and puts in into the ViewData (REDIRECT TO STEP 3)
(GET)You want to redisplay this data on a summary page.
Under those assumptions, lets clean up your code a bit, leverage the use of the ViewData and TempData objects and see if we can make this work.
Information Action
public ActionResult Information()
{
//In a strongly typed view, typically you would send an empty model
//so the model binder/Html.Input helpers have something to bind to
return View(new Models.Information());
}
Information POST to handle incoming data
[HttpPost]
public ActionResult Information(Models.Information info)
{
//Yup - you can use the same action name as the GET action above
//You can name this anything you want, but I typically keep the same names so
//I know where the data came from
//I think your assignments are backwards. info came into the controller action
//You want to save this as ViewData. Also, let's do that in one line of code
//And since we are redirecting, lets use the TempData dictionary
//Notice the method type decorator above [HttpPost]. This is the P in PRG (Post)
if(modelState.IsValid()){
TempData["info"] = info;
//Notice the name of the ActionMethod below. The is the R in PRG (Redirect)
return RedirectToAction("Summary");
}
//There were errors, lets send back to the Information view
return View(info);
}
Summary Action
public ActionResult Summary()
{
//We were redirected here, and this is a GET method. This is the G in PRG
//(GET)
//lets go ahead and set the TempData stuff to a model, it just looks nicer on
//the view
var model = TempData["info"];
return View(model);
}
As for the views, here is a snippet of what each might look olike
Information View
#model Models.Information
#{using(Html.BeginForm()){
#Html.LabelFor(x=>x.FirstName)<br/>
#Html.TextBoxFor(x=>x.Firstname)
//Repeat for each property
<input type="Submit" value="Submit"/>
}}
Summary View
#model Models.Information
#Html.LabelFor(x=>x.FirstName)<br/>
#Html.DisplayFor(x=>x.Firstname)
//Repeat for each property
Small Question at the end of a very long explanation ...
Assuming the Admin User belonging to Admin Role and the Regular User belonging to User Role attempt to access the Index page with the following route registered in Global.asax.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional },
new[] {"tst.Controllers"}
);
In the HomeController, the Index Action Method is decorated with the Authorize attribute.
[Authorize]
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
Forcing the anonymous user to logon.
If the Admin User logs in with his/her credentials, I would like to redirect him/her to the Index Action Method in the HomeController located in the Admin area.
If a Regular user logs in, I would like to redirect him/her to the Index Action Method in the HomeController located in the User area.
I have the following code in UserAreaRegistration.cs
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"User",
"Profile/{action}",
new { area = AreaName, Controller = "Home", action = "Index" },
new { RoleConstraint = new RoleConstraint()},
new[]{ "tst.Areas.User.Controllers"}
);
}
and the following code for AdminAreaRegistration.cs
public override void RegisterArea(AreaRegistrationContext context)
{
context.MapRoute(
"Admin",
"Profile/{action}",
new { area = AreaName, Controller = "Home", action = "Index" },
new { RoleConstraint = new RoleConstraint()},
new[]{ "tst.Areas.Admin.Controllers"}
);
}
Where the RoleConstraint is defined as follows
public class RoleConstraint: IRouteConstraint
{
public bool Match(
HttpContextBase httpContext,
Route route,
string parameterName,
RouteValueDictionary values,
RouteDirection routeDirection)
{
RoleProvider rp = new tst.Providers.CustomRoleProvider();
string[] roles = rp.GetRolesForUser(httpContext.User.Identity.Name);
if (roles != null && roles.Length > 0)
{
string roleName = roles[0];
string areaName = route.Defaults["area"].ToString();
return areaName == roleName;
}
return false;
}
}
The stock standard LogOn Action Method in the AdminController in the main Controllers folder...
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (Membership.ValidateUser(model.UserName, model.Password))
{
FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl)
&& returnUrl.Length > 1
&& returnUrl.StartsWith("/")
&& !returnUrl.StartsWith("//")
&& !returnUrl.StartsWith("/\\"))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Question:
Am I right in thinking that, When the Admin/Regular User is validated he/she must be redirected in this line in the code snippet above
return RedirectToAction("Index", "Home");
to the appropriate Index Action Method(Read: Index Action Method in the appropriate Area).
If so, I would like to know how.
I am confused because a constant string "Profile" is involved and it is not the usual stuff involving an action method and a controller name. "Profile" is neither a controller nor an action method.
Inspired by this post
MVC role-based routing
Instead of
return RedirectToAction("Index", "Home");
in the LogOn Action Method, I replaced it with
return Redirect("/Profile");
It worked !!!
However, what I don't understand is, when I click Log Off, it renders the Index page in the main Views folder. So I have to click LogOff again to be taken back to the LogOn page.
Whenever I try to upload a file to a server the current View is redirected to a different View from the controller. How can I upload a file and stay on the same View.
I have tried the following code:
public Action Result(HttpPostedFileBase file)
{
return new EmptyResult();
}
Return View();
Should work as you'd expect, returning the View named Result.
If the current Action Method isn't the view you'd like to return you can use:
return RedirectToAction("actionmethodname");
I would suggest using something like plupload for async upload. That way you can upload without redirect and even view image/document when upload is complete.
It allows multiple upload and fallback through different methods to successfully upload a file.
For implementation you just create another controller just for handling uploads.
Check my code for article submission in MVC architechture.
public ActionResult Submit(ArticleViewModel newSubmit, HttpPostedFileBase uploadFile)
{
if (ModelState.IsValid)
{
//Upload File
if (uploadFile != null)
{
string fileName = uploadFile.FileName;
newSubmit.Article.image = fileName;
uploadFile.SaveAs("~/Content/Uploads/Images");
string savedFileName = Path.Combine(Server.MapPath("~/Content/Uploads/Images"), uploadFile.FileName);
}
// The HTML comes encoded so we decode it before insert into database
newSubmit.Article.content = HttpUtility.HtmlDecode(newSubmit.Article.content);
//Set article flags
newSubmit.Article.flagged = true;
newSubmit.Article.finished = false;
newSubmit.Article.submitStoryFlag = true;
//Insert article in the database _repository.AddArticle(newSubmit);
return View("Submitted");
}
else
{
// Invalid – redisplay with errors
return View(newSubmit);
}
}
Suppose your view name is UploadView.cshtml and from there, you are uploading file.
UploadView.cshtml
#using (Html.BeginForm("UploadFile", "MyController", FormMethod.Post, new { enctype = "multipart/form-data", id = "frm", name = "frm" }))
{
<input id="FileAttachments" type="file" name="FileAttachments" />
<input type="submit" value="upload" />
}
Your Controller would be
MyController.cs
[HttpGet]
public ActionResult UploadView()
{
Return View();
}
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase FileAttachments)
{
if (FileAttachments != null)
{
string fileName = System.Guid.NewGuid().ToString() + Path.GetFileName(FileAttachments.FileName);
fileName = Path.Combine(Server.MapPath("~/Content/Files"), fileName);
FileAttachments.SaveAs(fileName);
}
return View("UploadView");
}
The button name is not being passed to my action method.
Here is my view (simplified):
#using (Html.BeginForm("HandleSubmit", "Home", FormMethod.Post))
{
<input id="btnAddLineItem" type="submit" name="AddLineItem" value="AddLineItem" />
}
Here's the controller method:
[HttpPost, ActionName("HandleSubmit")]
public ActionResult HandleSubmit(int? id, string btnSubmit)
{
switch (btnSubmit)
{
case "AddLineItem":
break;
case "AddNewOrder":
break;
}
return View("OrderDetails");
}
The btnSubmit value is always null. What do I need to do differently?
The name is what gets bound to your method signature, not the id.
Use the following:
public ActionResult HandleSubmit(string AddLineItem, string AddNewOrder)
{
/* ... code ... */
if(!string.IsNullOrEmpty(AddLineItem)) {
}
else if(!string.IsNullOrEmpty(AddNewOrder)) {
}
/* ... code ... */
}
Remember the form post will send a multipart/form-data collection of name/value pairs to the server.
You are not sending the button ID in any name or value in way whatsoever.
I suggest you make a model that has the following two properties:
In the get method make an instance of the model:
public ActionResult HandleSubmit()
{
MyModel model = new MyModel();
return View(model);
}
In the post method use the property of the model to get your values.
[HttpPost, ActionName("HandleSubmit")]
public ActionResult HandleSubmit(MyModel model)
{
switch (model.Order)
{
case "AddLineItem":
break;
case "AddNewOrder":
break;
}
return View("OrderDetails");
}
Your view can be something like the following:
#model MvcApplication3.Controllers.MyModel
#using (Html.BeginForm("HandleSubmit", "Home", FormMethod.Post))
{
#Html.EditorFor(x => Model.Order)
<input id="btnAddLineItem" type="submit" name="AddLineItem" value="AddLineItem" />
}