Post form to other controller - c#

I have one HomeController that is for landing page (home,about,contact us) and in home view I have registration of two types(2 separate viewmodels) and login (another viewmodel).I would like to know if there is a way to post form from index view ( HomeController ) to another controller.I'm trying to do this with tag helpers, but it seems it doesn't work. Here`s my code where i'm trying to do this
<form asp-controller="Employee" asp-action="Register" method="post" role="form" class="ui large form">
....
</form>
And here is my Register action in Employee controller
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(EmployeeRegisterViewModel employeeRegisterModel)
{
if (ModelState.IsValid)
{
IdentityResult result = await _service.CreateEmployeeAccount(employeeRegisterModel);
if (result.Succeeded)
{
return RedirectToAction(nameof(EmployeeController.Index), "Employee");
}
AddErrors(result);
}
return View(employeeRegisterModel);
}
Thanks for help

use the razor syntax Html.BeginForm
#using (Html.BeginForm("ActionName", "ControllerName", FormMethod.Post, new { #class = "ui large form"}))
{
}
Or in plain HTML do this
<form action="/ControllerName/ActionName" asp-action="Register" method="post" role="form" class="ui large form">
....
</form>

#using (Html.BeginForm("Register", "YourController", FormMethod.Post, null))
{
<input type="submit" value="Html PsBk Click" />
}

Related

How to manage multiple submit button in my case in MVC 5?

I am a beginner to MVC, I am using MVC 5
_Layout.cshtml code
_Layout.cshtml has navbar, it contains Logout, More button if user already loggedin, Also, it will render body part(Index.cshtml)
//Navbar
#if (ViewBag.name != null)
{
<input type="submit" class="dropdown-item" formaction="Logout" value="Logout" id="btnLogout" />
}
else{
<a class="nav-link" href="#">Login & Signup</a>
}
<input type="submit" class="dropdown-item" formaction="More" value="More" id="btnMore" />
//body
<div class="container body-content">
#RenderBody() //Index.cshtml
</div>
Index.cshtml
Index.cshtml it has some links and also some buttons and anchor links, and it will call partial view (_Login)
#using TestProject.Models
#model ViewSignInAndSignUp
//some html code
<input type="submit" class="dropdown-item" formaction="Action1" value="Action1" id="btnAction1" />
<input type="submit" class="dropdown-item" formaction="Action2" value="Action1" id="btnAction2" />
#Html.Partial("_Login") //partialview
_Login.cshtml
_Login.cshtml this one partial view, if user visit any links, this partial view will popup to request the user to make login. This partial view buttons are working
#model TestProject.Models.SignIn
#using (Html.BeginForm("ControllerSignIn", "Home"))
{
#Html.TextBoxFor(si => si.userName, new { #class = "form-control", #id = "txtLogin" })
#Html.TextBoxFor(si => si.password, new { #class = "form-control", #id = "txtPassword", #type = "password" })
<input type="submit" class="btn btn-sm btn-primary btn-rounded" value="Login" id="btnLoginSubmit" />
}
HomeController
[HttpPost]
public ActionResult Logout(string submitButton)
{
// some coding
return RedirectToAction("Index", "Home");
}
[HttpPost]
public ActionResult More(string str1)
{
// some coding
return RedirectToAction("Index", "Home");
}
[HttpPost]
public ActionResult Action1(string str1)
{
// some coding
return RedirectToAction("Index", "Home");
}
[HttpPost]
public ActionResult Action2(string str1)
{
// some coding
return RedirectToAction("Index", "Home");
}
Now, How can I manage all the buttons from _Layout.cshtml, Index.cshtml, _Login.cshtml(Partial view)
Note
my login button is working, but, logout, more, action1, action2 buttons are not working
Replace this
<input type="submit" class="dropdown-item" formaction="Logout" value="Logout" id="btnLogout" />
with this
Logout
Replace the href with the logout endpoint for your application if different than stated above. Remove any form pointing you to the logout endpoint also as it is not needed anymore.
The submit button submits the form using action URL defined in <form> tag, if you want to use multiple submit buttons then you need to wrap them inside multiple forms with different values of action attribute.
However, there's no need to use multiple submit buttons for those action methods, because redundant <form> tags are inefficient. You may just use #Html.ActionLink() helper to call them like this (and then use styling for those links to look like a button):
#Html.ActionLink("Logout", "Logout", "Home", null, new { #class = "dropdown-item", #id = "btnLogout" })
If the action contains parameter(s), you should add routeValues like example below:
#Html.ActionLink("Action1", "Action1", "Home", new { str1 = "SomeValue" }, new { #class = "dropdown-item", #id = "btnAction1" })
And change HTTP method to GET because ActionLink helper generates anchor <a> tag with href attribute which should use GET method:
[HttpGet]
public ActionResult Logout()
{
// some coding
return RedirectToAction("Index", "Home");
}
The same treatment should be applied to More, Action1 and Action2 action methods as well.
Further reference:
ActionLink helper

Send string from View to Controller using httpGet - MVC

I am new to MVC so please bear with me.
I am trying to send a string from a textbox to a controller method so I can find an object in a database. However, I do not know how to send the string successfully from the view to the controller in a HttpGet request (only in HttpPost)
The code in my view
<div>
<label>Email</label>
#Html.TextBox("email")
</div>
<div class="btn btn-success">
#Html.ActionLink("Edit RSVP", "Edit")
</div>
The ViewResult method in my controller
// Problem is the email parameter is always null
[HttpGet]
public ViewResult Edit(string email)
{
// If the email the typed is find, it will display their contents on to a RsvpForm view
return View("RsvpForm", guestRepository.Find(email));
}
Anyone know how I can send this string through, I would be grateful.
Thanks
Like this:
#using (Html.BeginForm("Edit", "ControllerName", FormMethod.Get))
{
<div>
<label>Email</label>
#Html.TextBox("email")
</div>
<div class="btn btn-success">
<input type="submit" value="Edit RSVP" />
</div>
}
Note: I can't tell from your description whether or not you are trying to do this without reloading the page. This option will post the page to the controller, so you will get a page reload.
If you want this to load without posting the page, you can look into Ajax.BeginForm. Here is a StackOverflow article with a decent primer on the AJAX form.
update
For your example, you may could do something like this if you want to use AJAX. This is all untested, but may be close to what you would need.
First you can create a partial view that represents the user data that you want to display:
RsvpForm.cshtml
#model GuestData
<div class="hdr">Name</div>
<div class="value">#Model.Name</div>
<div class="hdr">Email</div>
<div class="value">#Model.Email</div>
Then you want to make sure that your controller returns the partial view based on the email that is sent via the GET:
GuestDataController.cs
[HttpGet]
public ActionResult Edit(string email)
{
// If the email the typed is find, it will display their contents on to a RsvpForm view
return PartialView("RsvpForm", guestRepository.Find(email));
}
Then you create the AJAX form to submit the request via a GET and load the partial view without reloading the page: view.cshtml
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")" type="text/javascript"></script>
#using (Ajax.BeginForm("Edit", "GuestData", null, new AjaxOptions { UpdateTargetId = "UserData", HttpMethod = "Get" }, null))
{
<div>
<label>Email</label>
#Html.TextBox("email")
</div>
<div class="btn btn-success">
<input type="submit" value="Edit RSVP" />
</div>
}
<div id="UserData"></div>
The easiest way to do it is to create a form as follow :
#using(Html.BeginForm("Edit", ControllerName, FormMethod.GET))
{
#Html.Label("Email")
#Html.TextBox("email")
<input type="submit" value="Edit RSVP"/>
}
or you can use Jquery to change the link when textbox value change (which I do not recommend):
$('input[name=email]').on('change' function()
{
var value = $(this).val();
var href = $('.btn').next('a').attr('href');
href += '?email='+value;
$('.btn').next('a').attr('href', href)
});

When using Html.Action in layout getting error: Child actions are not allowed to perform redirect actions

I'll try to keep this as brief as possible.. I have a ViewResult that I am rendering on my _layout.cshtml page. This ViewResult is in a controller called CommonController where I am keeping some actions and data that I need on every page. If it matters, my ViewResult is a simple form.
ViewResult and the CommonController
[Authorize]
public class CommonController : AuthenticatedBaseController
{
[ChildActionOnly]
public ViewResult OrgSwitch()
{
//do stuff
return View();
}
[HttpPost]
public RedirectToRouteResult OrgSwitch(string UserOrgs)
{
return RedirectToAction("Index", "Recruiter", new { orgId = UserOrgs, area = "InkScroll" });
}
}
In my _Layout.cshtml page I render it like so:
#Html.Action("OrgSwitch", new { controller = "Common", area = "MyArea" })
This is all working fine, but now I am adding some functionality elsewhere in the app. I had asp.net mvc5 scaffold out a controller and views for a class I need to CRUD against. Just the quick and dirty forms so I can test a couple of things. I am going into the create page to add a new item. warning, it is mvc scaffolding, very ugly:
#model inkScroll.Models.Vacancy
#{
ViewBag.Title = "Create";
}
<h2>Create</h2>
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="form-horizontal">
<h4>Vacancy</h4>
<hr />
#Html.ValidationSummary(true)
<div class="form-group">
#Html.LabelFor(model => model.JobRef, new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(model => model.JobRef)
#Html.ValidationMessageFor(model => model.JobRef)
</div>
</div>
// lots more ugly code
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</div>
</div>
}
When I click 'submit' in the controller it does the usually validation checks and stuff. If my form is valid, there is no problem. If there are modelstate issues, I get the child action error.
Any ideas?
EDIT to clarify, the razor page you see is a scaffolded page that posts to a seperate JobsController. The data being passed into the post of the 'create' page is working fine, I am only getting the error if the model validation fails.

Rendering partial view inside a view using AJAX

I'm trying to refresh a partial view inside of a view when a form is submitted. However, whenever I try it just renders the partial view as a normal view. Can someone tell me what I'm doing wrong?
Controller:
public ActionResult ChangeHeatName(string heatName, string updatedHeat)
{
string user = User.Identity.Name;
HomeModel H = new HomeModel();
H.ChangeHeatName(heatName, updatedHeat, user);
ChemViewModel mySlagViewModel = new ChemViewModel();
mySlagViewModel = H.QueryResults(heatName);
return PartialView("PartialChemAnalysis", mySlagViewModel);
}
Partial view form (contained in partial view, not main view):
#using (Ajax.BeginForm("ChangeHeatName", "Home", new AjaxOptions(){UpdateTargetId = "chemDiv" InsertionMode = InsertionMode.Replace}))
{
<section>
Heat Name:<input type="text" name="heatName" value="#Html.ValueFor(x => x.heatname)" style ="width:100px"/>
Change to:<input type="text" name="updatedHeat" value="" style="width: 100px" />
<input type="submit" name="ChangeHeatName" value="Change" />
</section>
}
Index view where partial view is being rendered:
#if(ViewBag.SearchKey == null)
{
<div class="content-wrapper">
<hgroup class="title">
<h1>#HttpContext.Current.User.Identity.Name</h1>
<h2>#ViewBag.Message</h2>
</hgroup>
</div>
}
#using (Html.BeginForm("Index", "Home", "POST"))
{
<div class="searchField">
<input type="text" class="search-query" name="heatSearch" placeholder="Search">
<button class="btn btn-success" type="submit">Search</button>
<br />
#if (ViewBag.AverageSuccessful == true)
{
<input type="text" name="AvgConfirmation" class="search-query" value="Average Submitted Successfully" width:"400px" placeholder="Search" />
}
</div>
}
#if(ViewBag.SearchKey != null)
{
<div>
<div id ="chemDiv">
#Html.Action("PartialChemAnalysis", "Home", (string)ViewBag.SearchKey)
</div>
<div id ="slafDiv">
#Html.Action("PartialSlagView", "Home", (string)ViewBag.SearchKey)
</div>
</div>
}
Index controller that passes SearchKey:
[HttpPost]
public ActionResult Index(string heatSearch)
{
ViewBag.SearchKey = heatSearch;
return View();
}
Currently your ajax.beginform is in your partial view, that's all fine and dandy, but your partialview is not rendered inside your index, so really your never doing the ajax replace logic you're just calling a the action method and getting a full page refresh of the partial view.
here's what would work.
#if(ViewBag.SearchKey != null)
{
<div>
<div id ="chemDiv">
#Html.Partial("ChangeHeatName")
</div>
<div id ="slafDiv">
#Html.Action("PartialSlagView", "Home", (string)ViewBag.SearchKey)
</div>
</div>
}
Now your Ajax.Beginform is rendered in the index view, and when the button is clicked it will refresh.
Edit: you'll need to do something with #Html.Action("PartialChemAnalysis", "Home", (string)ViewBag.SearchKey) possibly stick it in your partial view, because everything in "chemDiv" will now be replaced upon update.
You're not specifying POST in Ajax.BeginForm(). Try this:
#using (Ajax.BeginForm("ChangeHeatName", "Home", FormMethod.Post,
new AjaxOptions(){UpdateTargetId = "chemDiv" InsertionMode = InsertionMode.Replace}))
{...}
Also, stick a breakpoint on your controller action and step through it, see if it's actually hitting return PartialView() or skipping over it.
Posting this because it's not an intuitive fix. Apparently there are issues with MVC 4 and jQuery 1.9.1 so to get this to work I had to change my reference to jQuery 1.7.1

Model not being passed to rendered view

I am having an issue getting data in my model on my MakePayment.cshmtl view.
The AccountScreen.cshtml is calling the MakePayment.cshtml view:
#model SuburbanCustPortal.SuburbanService.CustomerData
#{
ViewBag.Title = "Account Screen";
}
<h2>AccountScreen</h2>
<div class="leftdiv">
<fieldset>
<legend>customer info</legend>
#Html.Partial("CustomerInfoPartialView", Model)
</fieldset>
<fieldset>
<legend>delivery address</legend>
#Html.Partial("DeliveryAddressPartialView", Model)
</fieldset>
<fieldset>
<legend>delivery info</legend>
#Html.Partial("DeliveryInfoPartialView", Model)
</fieldset>
</div>
<div class="rightdiv">
<fieldset>
<legend>balance</legend>
<div>
#Html.Partial("BalancePartialView", Model)
</div>
</fieldset>
<fieldset>
<legend>payment</legend>
<div>
#Html.Partial("MakePayment", Model)
</div>
</fieldset>
<fieldset>
<legend>billing info</legend>
<div>
#Html.Partial("BillingInfoPartialView", Model)
</div>
</fieldset>
</div>
My MakePayment.cshtml view:
#model SuburbanCustPortal.SuburbanService.CustomerData
#using (Html.BeginForm("MakePayment2", "Customer", FormMethod.Post))
{
<div style="text-align:center;">
<input class="makePaymentInput" type="submit" value="Make a Payment" />
</div>
}
My CustomerController:
public ActionResult AccountScreen(LogOnModel model)
{
return ShowCustomer(model.AccountNumber);
}
public ActionResult MakePayment(CustomerData model)
{
return View("MakePayment", model);
}
[HttpPost]
public ActionResult MakePayment2(CustomerData model)
{
//CustomerData model = new CustomerData();
var newmodel = new PaymentModel.SendToGateway();
newmodel.AccountBalance = model.TotalBalance;
newmodel.Amount = model.TotalBalance;
return RedirectToAction("PrePayment", "Payment", newmodel);
}
The public ActionResult MakePayment(CustomerData model) is never being reached.
My problem: The [HttpPost] public ActionResult MakePayment2(CustomerData model) is being reached but the model has nulls in it.
I know the data initial model from the AccountScreen is being populated since the other views that are being rendered is showing data.
Anyone see what I am doing wrong?
The problem is there's nothing inside your form except a submit button. You need to make sure input fields are there (either text boxes, select lists, or hidden fields), as those are what post data back to the controller.
You could try using EditorForModel inside your partial view:
#using (Html.BeginForm("MakePayment2", "Customer", FormMethod.Post))
{
#Html.EditorForModel()
<div style="text-align:center;">
<input class="makePaymentInput" type="submit" value="Make a Payment" />
</div>
}
Edit based on comments
Razor doesn't include an Html.HiddenForModel() method, for whatever reason. Possible workarounds:
List out each property of the model using Html.HiddenFor(model => model.Property)
Annotate the model properties with \[HiddenInput\]
Use EditorForModel() but wrap it in <div style="display: none;"></div> (NOTE that a malicious user can still modify the properties as if they were visible.)
Use only Html.HiddenFor(model => model.id) and fetch the model in the controller.
Use the serialization method in the MVC Futures assembly
Related quesion here:
Is there some way to use #Html.HiddenFor for complete model?
The problem is, you are creating a form containing nothing else than a submit button.
When you submit it, it posts nothing back to the server, thus your function receives an empty model.
#using (Html.BeginForm("MakePayment2", "Customer", FormMethod.Post))
{
<div style="text-align:center;">
<input class="makePaymentInput" type="submit" value="Make a Payment" />
</div>
}
This translates as :
<form method="POST" action="{url}">
<div style="text-align:center;">
<input class="makePaymentInput" type="submit" value="Make a Payment" />
</div>
</form>
More details :
Since in the logic you then redirect to a new page to collect payment information, you don't want to give the user the opportunity to mess with your model, thus you should query your customer data from your Context instead of trusting what is submitted in the POST.
Thus all you really need to add if this :
#using (Html.BeginForm("MakePayment2", "Customer", FormMethod.Post))
{
#Html.HiddenFor(model => model.{ID Field})
<div style="text-align:center;">
<input class="makePaymentInput" type="submit" value="Make a Payment" />
</div>
}
This way, you will be able to get your model back in the server side code.
Basically, your form submits nothing as there are no input fields inside the form scope. Try to wrap all your html in AccountScreen.cshtml within #using (Html.BeginForm( statement (and throw it out from MakePayment.cshtml).

Categories