I have this button:
<button type="button" onclick="location.href='#Url.Action("Index", "Registration">Register</button>
Its on a sign-in page that has this link which goes to a registration page. I'd like to preserve the username and password entered on this page when the user clicks the link to go to the registration page, so is there a way to pass it a new model such that the user goes to the registration page and already has their ID and password entered?
For example, I am trying to do something like this:
<button type="button" onclick="location.href='#Url.Action("Index", "Registration", new RegistrationModel { ID = Model.ID, Password = Model.Password })'">Register</button>
All you need to do is just post your values to which ever controller you want to handle it and share the same textbox names.
Say you have a view like so, containing your form:
#model LoginFormViewModel
#* Form element defaults to posting to Login controller, but has an attribute containing the URL to the Registration controller should we need it *#
<form id="login_form" method="post" action="#Url.Action("Index", "Login")" data-registration-url="#Url.Action("Index", "Registration")">
#* Username field *#
#Html.TextBoxFor(x => x.Username)
#* Password field *#
#Html.PasswordFor(x => x.Password, new { value = Model.Password })
#* Hidden value that we can check in the controller *#
<input type="hidden" name="FromLoginPage" value="true" />
<input type="submit" value="Register" id="register_submit" />
<input type="submit" value="Login" />
</form>
I would use jQuery to control the submitting of the forms:
// User clicked regstration button, not login button
$(document).delegate('input#register_submit', 'click', function(e) {
// Prevent default submitting of the form to the login controller
e.preventDefault();
// Get registration URL from the attribute
var registerActionUrl = $('form#login_form').attr('data-registration-url');
// Submit the form to the registration controller
$('form#login_form').attr('action', registerActionUrl).submit();
});
Here's the model LoginViewModel and RegistrationViewModel that share properties with the same names (Username and Password), this will come in handy for binding up depending on which controller we submit the form to:
// Login model
public LoginViewModel
{
public string Username { get; set; }
public string Password { get; set; }
}
// Registration view model
public RegistrationViewModel
{
public string Username { get; set; }
public string Password { get; set; }
public bool FromLoginPage { get; set; }
// ... other fields that won't get bound when submitted from login page
public string ConfirmPassword { get; set; }
}
In the Login controller we handle things normally, but within the registration form we can do a quick check on FromLoginPage submitted from the login page to return the registration page back to the user with the fields populated:
// Login controller
[HttpPost]
public LoginController : Controller
{
public Index(LoginViewModel requestmodel)
{
// Validate login
// Process login
// Return the view
return View(requestmodel);
}
}
// Registration controller
[HttpPost]
public RegistrationController : Controller
{
public Index(RegistrationViewModel requestModel)
{
// Submitted from the login page?
if (requestModel.FromLoginPage)
{
// Clear any model validation errors so far
this.ModelState.Clear();
// Just load the registration page with the values populated
return View(requestmodel);
}
// A normal registration request from registration page, perform validation on entire model
// Process login here
return View(requestmodel);
}
}
Related
Using ASP.NET MVC, in my view, I list some files and show them as a button. By clicking each button the corresponding file should be downloaded.
To show the list of files, I pass a model to view and when a user clicks on each of those buttons, I have to send the filename plus the original model back to the controller.
I found answers for a similar question but in my case, I don't have only one button. I have one button for each filename that I render on view.
This is the code for my view:
#using (Html.BeginForm("DownloadFile", "SharedFolder", FormMethod.Post))
{
<div class="col-sm-6">
<div class="panel panel-info">
<div class="panel-heading">Files</div>
<div class="panel-body" style="max-height:300px; height:300px; overflow-y:scroll">
#foreach (var file in Model.Files)
{
<button type="button" class="btn btn-link btn-sm" onclick="location.href='#Url.Action("DownloadFile", "SharedFolder", new { fileToDownload = file, data = Model })'">
<div class="glyphicon glyphicon-file" style="color:dodgerblue">
<span style="color:black;">#file</span>
</div>
</button>
<br />
}
</div>
</div>
</div>
}
And my controller action:
[HttpPost]
public ActionResult DownloadFile(string fileToDownload, FolderExplorerViewModel data)
{
// download the file and return Index view
return RedirectToAction("Index");
}
When I click on a file to download it, I get below error:
The resource cannot be found.
Requested URL: /SharedFolder/DownloadFile
Update:
This is my ViewModel
public class FolderExplorerViewModel
{
public int ID { get; set; }
public List<Folder> Folders { get; set; }
public List<string> Files { get; set; }
public string SelectedPath { get; set; }
}
You shouldn't store data = Model like this causes the performance and security problem.
You just store one fileToDownload value from View. After that, in Controller, You should get file by fileToDownload param.
[HttpPost]
public ActionResult DownloadFile(string fileToDownload)
{
// download the file by `fileToDownload` param here
return RedirectToAction("Index");
}
The reason why you are getting that error is because, its trying to do form post and there are no form html elements representing fileToDownload and data.
Actually, instead of using form POST you can use anchor tags invoking controller GET action (since its just download, no need to use POST here). As #Phong mentioned, using fileToDownload you probably can retrieve other information which is needed for redirection to Index.
#foreach (var file in Model.Files)
{
#file
}
and then your controller action will be:
public ActionResult DownloadFile(string fileToDownload)
{
// do the stuff
// download would return FileResult on success, not sure what you meant by RedirectToAction("Index")
// download the file and return Index view
return RedirectToAction("Index");
}
If you still wanted to send Model, then you can do that via javascript button click event with ajax.
I have 2 Tables: tblClient and tblActivity.
tblClient's Primary Key is an int called clientID.
tblActivity has a Foreign Key of the same nature (int clientID)
What I'm trying to do is make a Create View for a tblActivity Record,
that captures the clientID of the Client who is currently watching his list of Activities and inputs it in the form.
I already have the list of activities view.
I've been having troubles with understanding how to send an int to my View from the Get Method for the Activity in my controller, and how to make the #Html.hiddenFor in my view to capture it and send it back to the Post method.
Create a view model for this view
public class CreateActivity
{
public int ClientId { set;get;}
public string Title { set;get;}
}
Now in your create view, accept the client id in the url, create an object of CreateActivity view model, set the ClientId property value and send that to the view.
public ActionResult Create(int id)
{
var vm = new CreateActivity { ClientId = id };
return View(vm);
}
Now in your view
#model CreateActivity
#using(Html.BeginForm())
{
#Html.TextBoxFor(s=>s.Title)
#Html.HiddenFor(s=>s.ClientId)
<input type="submit" />
}
Since ClientId is stored in as hidden form field, it will be available when you submit the form.
[HttpPost]
public ActionResult Create(CreateActivity model)
{
// check model.ClientId
// to do : Return something
}
I have one simple form with two buttons inside. Each button has to redirect me on different view in my controller. I was looking for some examples over the net, found solutions and implemented them. Unfortunately, it isn't working for me.
Controller:
public class HomeController : Controller
{
private MovieEntities db = new MovieEntities();
[HttpGet]
public ActionResult Index()
{
return View();
}
[HttpPost]
[Button(ButtonName = "clickButton", ButtonValue = "Send")]
public ActionResult Send()
{
return View();
}
[HttpPost]
[Button(ButtonName = "clickButton", ButtonValue = "Reset")]
public ActionResult Reset()
{
return View();
}
}
Index view:
#model IEnumerable<CustomWizzardMVC.Models.MovieInfo>
#{
ViewBag.Title = "Home";
}
<h1>Insert informations</h1>
#using(Html.BeginForm())
{
<input type="button" name="clickButton" value="Send" />
<input type="button" name="clickButton" value="Reset" />
}
Send and Reset view are just simple views with <p> tags inside.
I have Button class too:
public class Button : ActionNameSelectorAttribute
{
public string ButtonName { get; set; }
public string ButtonValue { get; set; }
public override bool IsValidName(ControllerContext controllerContext, string actionName, System.Reflection.MethodInfo methodInfo)
{
return controllerContext.HttpContext.Request[ButtonName] != null && controllerContext.HttpContext.Request[ButtonName] == ButtonValue;
}
}
What am I doing wrong in here? Also, if you know some other way to do the same functionality without using jQuery, please post some code :)
You can configure a form's target by it's action attribute.
So you can do this by changing your form's action attribute. You need to use client side script to do that.
An another option, you can send a value that contains user's option (like Option = "reset" or Option = "send"). And decide what view you need to go in your default view.
Change your input type="button" to type="submit.
<input type="button" /> buttons will not submit a form - they don't do anything by default. They're generally used in conjunction with JavaScript as part of an AJAX application.
<input type="submit"> buttons will submit the form they are in when the user clicks on them, unless you specify otherwise with JavaScript.
Found how it can be done. <input type="submit" value="Send" formaction="#Url.Action("Send","Home")" /> Just found out that formaction is the new HTML5 attribute that specifies the URL of the form for the HttpPost action. :)
I want to create a registration URL that will pre-populate the registration page with URL parameters in MVC. For example I have 3 text form inputs txtName, txtEmail, and txtCode. When the user clicks the registration link with his Name, Email, and Code embedded in the URL they will arrive at the registration page with these fields already populated so all they have to do is pick a password and click register.
Can this be done using the URL and the View only or do I need to involve the Controler or Model?
How would the URL look in this example www.somedomain.com/home/register
What code needs to be implemented in the MVC if any?
A possible approach is to run JavaScript, on DOMContentLoaded, that'll take your query string params and pre-populate the applicable form fields. You can also do this on the server-side by accessing the Request.QueryString collection and populating the applicable input fields.
The MVC way to do this is to involve both the controller and the model.
Create a view model class containing the fields of the registration form.
Add the view model as the single parameter of the controller method.
Send that view model directly to the view.
The URL will be of form http://example.com/home/register?Name=Anders
The controller will be really short:
public ActionResult register(RegisterViewModel model)
{
return View(model);
}
The ViewModel should contain all properties that are present in the form:
public class RegisterViewModel
{
public string Name { get; set; }
public string Email { get; set; }
public string Code { get; set; }
}
In the view, use the Html helpers to build up the form.
#model RegisterViewModel
// Html header, body tag etc goes here...
#using(Html.BeginForm())
{
#Html.LabeFor(m => m.Name)
#Html.EditorFor(m => m.Name)
#Html.ValidationMessageFor(m => m.Name)
// Rest of fields goes here
<button>Submit</button>
}
so I have a Url Action
Create new teacher & assign to account.
That passes in two routeValues: createAndAssign, and teacherID.
Now when I go to my Teacher/Create page, my URL is like so:
.../Teacher/Create?createAndAssign=True&teacherID=ea817321-5633-4fdc-b388-5dba2c4a728e
Which is good, I want this. Now when I POST to create my teacher, how do I grab createAndAssign and teacherID value?
You can set the Querystring value in a hidden variables in the form and render in your GET action method and accept that in your POST action method.
View rendered by your GET Action
#using (Html.BeginForm())
{
//Other form elements also
#Html.Hidden("teacher",#Request.QueryString["teacherID"] as string)
#Html.Hidden("createAndAssign",#Request.QueryString["createAndAssign"]
as string)
<input type="submit" />
}
and now have a teacher parameter and createAndAssign parameter in your HttpPost action method so that it will be available when you submit the form.
[HttpPost]
public ActionResult Create(string teacher,string createAndAssign)
{
//Save and Redirect
}
If your view is strongly typed (which is my personal preference), it is quite easy,
public ActionResult GET(string teacherID,string createdAndAssing)
{
var yourVMObject=new YourViewModel();
yourVMObject.TeacherID=teacherID;
yourVMObject.CreateAndAssign=createdAndAssing;
return View(createdAndAssing);
}
and in your strongly typed view,
#model YourViewModel
#using (Html.BeginForm())
{
//Other form elements also
#Html.HiddenFor(x=>x.TeacherID)
#Html.HiddenFor(x=>x.CreateAndAssign)
<input type="submit" />
}
And in your POST action
[HttpPost]
public ActionResult Create(YourViewModel model)
{
//look for model.TeacherID
//Save and Redirect
}
you can get the value from the query string or as params of the controller like
var x =Request.QueryString["createAndAssign"];
or
public ActionResult Create(bool createAndAssign, string teacherID){
return View();
}