How should I setup Registration controller action? - c#

I am fairly new to MVC and i'm looking for advice on how to setup a particular registration controller.
I have a controller called AccountController which has a Register method and I have a Register.cshtml.
Now, one of the biggest problems I seem stuck on is that I have 2 dropdowns that I need to populate based on the response from a service as these values change depending on location and other various parameters.
I have my page started and loading but I'm not sure what to do once a user click 'register'.
#model Adw.Models.RegisterModel //This is my model
#Html.DropDownListFor(m => m.States, new SelectList(Model.States)); // I load my dropdowns here
[AllowAnonymous]
public ActionResult Register(RegisterModel model)
{
model.States = Services.GetStates().Payload;
model.Countries = Services.GetCountries().Payload;
return View(model);
}
So my question is, when a user submits the form, should it come back to this same method? If so what would be the best way to validate that this is a submit rather than an initial load?
Also i haven't done much in the way of error handling and could use a suggestion on that, such as if either of the above service calls fail, then a registration cannot be completed, should that direct to a new page or is there a easy way to build that kind of error into the same page?

You should create two different method. One for GET and second for POST request:
[AllowAnonymous]
[HttpGet]
public ActionResult Register()
{
...
}
[AllowAnonymous]
[HttpPost]
public ActionResult Register(RegisterModel model)
{
if (ModelState.IsValid)
{
// create user
return this.RedirectToAction("SignIn");
}
else
{
return View(model);
}
}
You can review sample from default template.

Related

How to redirect to a post action from a get action mvc

I have the following Get action:
[HttpGet]
[AllowAnonymous, OnlyAnonymous]
public ActionResult VerifyVoucherCode()
{
var model = new VerifyVoucherCodeModel();
model.VoucherCode = Request.GetFirstQueryValue("token", "voucherCode");
if (!string.IsNullOrEmpty(model.VoucherCode))
{
// prepopulates the code for the user already in a form
}
return View(model);
}
And a POST action for when the user submits the form:
[HttpPost, AjaxOnly]
[AllowAnonymous, OnlyAnonymous]
[ValidateAntiForgeryToken]
public ActionResult VerifyVoucherCode(VerifyVoucherCode model)
{
return ExecuteAction(() =>
{
// do something
});
}
I want to change the logic so that if the voucher code is in the request, the form is submitted automatically for the user without them having to submit the form themselves (i.e. it takes them straight to that Post action). I've looked at lots of Stack Overflow questions and answers and it seems I cannot redirect to the Post action. I have also tried creating a second Get action which calls the Post action but that does not work either. Does anyone know the correct way to approach this problem?
Thanks
Assuming the model contains a single string for the voucher, you can do something like this:
[HttpGet]
[AllowAnonymous, OnlyAnonymous]
public ActionResult VerifyVoucherCode(string id)
{
if(string.IsNullOrEmpty(id))
{
MyModel model1 = new MyModel();
...
return View(model1);
}
//otherwise process the voucher here
...
return RedirectToAction("SuccessMsg");
}

send model object from view to controller method ASP.NET MVC C#

I know there are a lot of questions about this, but not in a single one I've seen (and I've been searching for two hours now), did I see what to write in the razor view (.cshtml file) to fire the controller method associated with saving the model object to the database, or how that object is passed.
So I want to make a simple registration page. I created the Users model, created the view associated with the model, named Register.cshtml, and I access the view through the Account controller which has a Register method:
public ActionResult Register()
{
return View();
}
The tutorial I follow uses the default code generated in the View when you create it for the Users model.
<input type="submit" value="Create" class="btn btn-default" />
And states that you should make a method in the Account Controller as follows:
public ActionResult Register(User obj)
{
if (ModelState.IsValid)
{
DatabaseEntities db = new DatabaseEntities();
db.Users.Add(obj);
db.SaveChanges();
}
return View(obj);
}
(where DatabaseEntities is the name of my database)
This doesn't work, because, on running the application, it says that it doesn't know which one of the two methods to fire.
System.Web.Mvc.ActionResult Register() on type Biblioteca.Controllers.AccountController
System.Web.Mvc.ActionResult Register(Biblioteca.Models.User) on type Biblioteca.Controllers.AccountController
This is the error I get.
I thought of renaming the second method RegisterPost(User obj), but then I don't know how to call the method with the argument, because in the razor view, I don't know which is the object that gets created on submitting the form.
I could use an #Html.ActionLink(), but I don't know how to send the object.
I actually tried adding an onclick method to the submit button, as follows:
onclick="location.href='#Url.Action("RegisterPost", "Account")'"
But after filling the form and clicking the submit button, nothing happens. Nothing gets inserted into the database.
I don't know what to do now. Please help.
Add attribute [HttpGet] to the first action and [HttpPost] to the second action:
[HttpGet]
public ActionResult Register()
{
return View();
}
[HttpPost]
public ActionResult Register(User obj)
{
if (ModelState.IsValid)
{
DatabaseEntities db = new DatabaseEntities();
db.Users.Add(obj);
db.SaveChanges();
}
return View(obj);
}
You can read more on MSDN
To expand a bit, try adding [HttpPost] above the second Action method.
[HttpPost]
public ActionResult Register(User obj)
{
if (ModelState.IsValid)
{
DatabaseEntities db = new DatabaseEntities();
db.Users.Add(obj);
db.SaveChanges();
}
return View(obj);
}

Razor form not passing back to controller method

I am trying to pass a textbox's text back to a method in my controller, but the data is not being passed in the parameter
I am genuinely confused, i'm following another example but i'm getting a different result, ie - my method behaving as if no parameter is passed
Code
public ActionResult Index(string searchString)
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
var listOfAnimals = db.Animals.ToList();
if (!String.IsNullOrEmpty(searchString))
{
listOfAnimals = listOfAnimals.Where(a => a.AnimalName.ToLower().Contains(searchString.ToLower())).ToList();
}
return View(listOfAnimals);
}
and here is my razor form from my view page
#using(Html.BeginForm("Index", "Home"))
{
#Html.TextBox("searchString")
<input type="submit" id="Index" value="Index" />
}
Can anybody spot why this isn't working?
If more code is needed, please let me know but i think the issue is isolated to here
You code is correct.
Since you didn't add [HttpGet] or [HttpPost] before index method.
This method was called twice.
The first call ran when producing the page with form via url http://server/Home/Index. This call was an http get and searchString mapped from URL was null, which is correct.
The second call ran when you clicked submit button. Correct value would be mapped by MVC correctly.
You need to have 2 Index actions (two methods), one without decorations (GET verb) and another one decorated with HttpPost (POST verb). Basically, when you go to the index page, the GET action is executed. When you submit the form, a POST request is executed and the Index decorated with HttpPost is executed.
// GET
public ActionResult Index() { ... }
// POST
[HttpPost]
public ActionResult Index(string searchString) { ... }
Francisco Goldenstein wrote the recommended way. It means you can have two Index() actions:
// for GET
public ActionResult Index() { ... }
// for POST
[HttpPost]
public ActionResult Index(string searchString) { ... }
However it is possible to have one Index() method for handling both (GET and POST) requests:
public ActionResult Index(string searchString = "")
{
if(!string.IsNullOrEmpty(searchString)
{ /* apply filter rule here */ }
}
You wrote, your code is not working. Do you mean, your action method is not requested after click on the button? Consider to allow empty value Index(string searchString = "")
If your action method is fired but variable is empty, check the name on the View() side. Textbox must not be disabled, of course.

Forbid access on page if form of another Action isn't submitted

I'm trying to create a registration in my ASP.NET MVC application. The registration is split in different areas.
First, I'm getting on the Create page. If the form in Create is successfully filled out and I submitted, I want to go on AccountInfo, which has another form.
[HttpGet]
public ActionResult Create()
{
return View("Create");
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Account account)
{
if(ModelState.IsValid)
{
using (db)
{
return RedirectToAction("AccountInfo", new { account = account });
}
}
return View();
}
public ActionResult AccountInfo(Account account)
{
db.Accounts.Add(account);
db.SaveChanges();
return View();
}
How can I forbid the access on AccountInfo if the form in Create isn't filled out?
Well, all you care about is that account is filled in, so you really don't have to worry about whether or not someone came to AccountInfo directly. If they do, they won't have a valid Account object. If the Account Object is not valid, then you just redirect them back to Create.
Check that all the parameters in your first form are "valid" and filled in by the time you reach the second form. You can also check that the call came from that page. Just inspect the http request object to find the right info.
Here is the object I am referring to: http://msdn.microsoft.com/en-us/library/system.web.httprequest%28v=vs.110%29.aspx

Post method that calls another one for returning the view

In an MVC4 project I need to "refresh" the page depending on some messages that can be present, otherwise I just redirect to a page, and if presenting again the page if them messages are present I would like to avoid just returning the View as it will cause then the double submission when the user tries to refresh it.
What I'm trying to do is this
[HttpGet]
public ActionResult SampleMethod()
{
viewModel = _builder.Build();
return View(viewModel);
}
[HttpPost]
public void SampleMethod(SampleViewModel viewModel)
{
if (ModelState.IsValid)
{
var response = serviceCall;
var errorMessages = response.ErrorMessages;
if (!errorMessages.Any())
{
//Redirect to proper view
}
else
vm = _builder.Build();
}
else vm = _builder.Build(); //There is some validation error I rebuild
CashbackOffersConfirmation(vm);
}
public ActionResult SampleMethodConfirmation(SampleViewModel viewModel)
{
return View("SampleMethod", viewModel);
}
It goes through the process
but the final page is .../SampleMethod instead of .../SampleMethodConfirmation and is blank,
Is this something to do with the routing (quite lost in this)? Is this a correct approach?
Thanks
In order to pass the object model from the view to the controller, you need to make a post request. Make sure you use a form that will generate the post request.
Also make the SampleMethodConfirmation method a post.
E.g.: add [HttpPost] on top of the method in the controller

Categories