So in my View I need a simple textbox like so:
<input type="text" name="CVR" placeholder="Enter CVR" required />
in the same view, at the end I have the submit button:
#Html.ActionLink("Submit", "SendMail", new { studentId = Html.ViewData.Model.StudentId, companyId = Html.ViewData.Model.CompanyId, applicationId = Html.ViewData.Model.ApplicationId, companyCVR = Model.CVR})
The data works, until the "companyCVR = Model.CVR". I am having trouble changing "companyCVR" to the text the user inputs in the textbox above.
This is my controller constructor:
public ActionResult SendMail(string studentId, string companyId, int applicationId, string companyCVR)
and technically, this should work:
contract.CVR = companyCVR;
It works when I hardcoded (contract.CVR = "12345"). My problem is passing the value from the textbox to companyCVR which I am trying to pass as a parameter to the controller.
How can I solve this?
It would probably be easier if you use a <form>. Something like:
#using (Html.BeginForm("SendMail", "Contract", null, FormMethod.Post), new { id = "myForm" })
{
<input type="hidden" value=#Html.ViewData.Model.StudentId name="studentId" />
<input type="hidden" value=#Html.ViewData.Model.CompanyId name="companyId" />
<input type="hidden" value=#Html.ViewData.Model.ApplicationId name="applicationId" />
<input type="text" name="companyCVR" />
}
<input type="button" value="Submit" onclick="$('#myForm').submit();" />
Related
Is it possible to clear a collection with model bindning?
Sample model class:
public class TestModel
{
public String Name
{
get; set;
}
public List<String> Strings
{
get; set;
}
}
Sample Html:
<form>
<input type="text" name="Name" value="New name" />
<input type="text" name="Strings[]" value="New str1" />
<input type="text" name="Strings[]" value="New str2"/>
<input type="text" name="Strings[]" value="New str3"/>
<input type="submit" />
</form>
And controller code:
public IActionResult Post()
{
var model = new TestModel() { Name = "Old name" };
model.Strings = new List<String>();
model.Strings.Add("Old str 1");
model.Strings.Add("Old str 2");
this.TryUpdateModelAsync(model);
}
In this case the TryUpdateModelAsync will update both Name and Strings but what if I would like to clear the list with TryUpdateModelAsync?
changing html to:
<form>
<input type="text" name="Name" valuye="New name" />
<input type="text" name="Strings" value="" />
<input type="submit" />
</form>
will of course update Strings to a list with one empty / null value and removing input for Strings will keep the old list intact (as expected), but is there any magic trick to just clear that list or set it to null?
I am thinking of having something like this:
#if(Model.ShowSubmitButton)
{
<input id="submitButton" type="submit" value="Update stuff" />
}
else
{
<input id="continueButton" type="submit" value="Continue to next page" />
}
Then in controller is it possible to know which button it is getting called from?
I originally had my controller method working with the first button, now adding a second button with different functionality, wanted to see if using the same method I can determine which button was clicked ? and if it is not possible this way, then what do you suggest?
Not without extra information. I would likely split them up rather than have two submit buttons for the same form doing two different things but if you really want to go down that road one way would be to add an additional posted variable that tells you which was clicked.
#if(Model.ShowSubmitButton)
{
<input type="hidden" name="submitStyle" value="update"/>
<input id="submitButton" type="submit" value="Update stuff" />
}
else
{
<input type="hidden" name="submitStyle" value="continue"/>
<input id="continueButton" type="submit" value="Continue to next page" />
}
To answer your additional question. Either you can add this variable to your model posted back or add it as an additional parameter.
// Where "MyModel" has a public property "SubmitStyle"
public ActionResult MyAction(MyModel model)
// Or an int, string, whatever type of parameter you want/need.
// In my example it was a string so...
public ActionResult MyAction(string submitStyle/*, <other params...>*/)
You could add a hidden field. Not ideal solution, but does the job.
#if(Model.ShowSubmitButton)
{
<input type="hidden" name="buttonClicked" value="1">
<input id="submitButton" type="submit" value="Update stuff" />
}
else
{
<input type="hidden" name="buttonClicked" value="2">
<input id="continueButton" type="submit" value="Continue to next page" />
}
In your controller you would accept it as:
public ActionResult MyAction(MyObject myobj, int buttonClicked)
There is an elegant way (tested only on chrome yet), define two inputs
<input type="submit" value="Next" name="Action"/>
<input type="submit" value="Prev" name="Action"/>
Now in you input model in controller put model defined like this:
public class MyModelDto
{
// other properties
public MyCustomAction Action { get; set; }
}
Where the
public enum MyCustomAction
{
Next=0,
Prev=1
}
Now check the value of action.
Update :
This is an SPA app.So it's having js file also for supporting the submit button.So I think problem is on it.Could you tell me how to modify it to support multiple kind of submit buttons ? At this moment I think it supports only for a single submit button.That is why it always get the first form's hidden field value I think.Thanks.
JS
var $loginForm = $('.login-form');
$loginForm.submit(function (e) {
e.preventDefault();
if (!$('.login-form').valid()) {
return;
}
abp.ui.setBusy(
null,
abp.ajax({
contentType: app.consts.contentTypes.formUrlencoded,
url: $loginForm.attr('action'),
data: $loginForm.serialize()
})
);
});
UI
VM
public class LoginViewModel
{
public string TenancyName { get; set; }
[Required]
public string UsernameOrEmailAddress { get; set; }
[Required]
public string Password { get; set; }
public bool RememberMe { get; set; }
}
CompanyLoginFormViewModel VM :
public class CompanyLoginFormViewModel
{
public LoginViewModel LoginViewModel { get; set; }
public List<TenantListDto> Tenants { get; set; }
}
*.cshtml page
#{
var companyLoginFormViewModel = TempData["CompanyLoginFormViewModel"] as CompanyLoginFormViewModel;
}
#foreach (var tenant in companyLoginFormViewModel.Tenants)
{
<form class="login-form" action="#Url.Action("Login")?returnUrl=#ViewBag.ReturnUrl" name="companyLoginForm" method="post">
<input type="hidden" name="usernameOrEmailAddress" value="#companyLoginFormViewModel.LoginViewModel.UsernameOrEmailAddress" />
<input type="hidden" name="password" value="#companyLoginFormViewModel.LoginViewModel.Password" />
<input type="hidden" name="rememberMe" value="true" />
<input type="hidden" name="companyUrl" value="true" />
<input type="hidden" name="tenancyName" value="#tenant.TenancyName" />
<div class="row margin-top-10">
<div class="col-xs-3">
<button type="submit" class="btn btn-success uppercase">#L("LogIn")</button>
</div>
</div>
</form>
}
Generated html
<form class="login-form" action="/Account/Login?returnUrl=/Application" name="companyLoginForm" method="post" novalidate="novalidate">
<input type="hidden" name="usernameOrEmailAddress" value="fake#gmail.com">
<input type="hidden" name="password" value="fake">
<input type="hidden" name="rememberMe" value="true">
<input type="hidden" name="companyUrl" value="true">
<input type="hidden" name="tenancyName" value="Asset_Management">
<div class="row margin-top-10">
<div class="col-xs-3">
<button type="submit" class="btn btn-success uppercase">Log in</button>
</div>
</div>
</form>
<form class="login-form" action="/Account/Login?returnUrl=/Application" name="companyLoginForm" method="post" novalidate="novalidate">
<input type="hidden" name="usernameOrEmailAddress" value="fake#gmail.com">
<input type="hidden" name="password" value="fake">
<input type="hidden" name="rememberMe" value="true">
<input type="hidden" name="companyUrl" value="true">
<input type="hidden" name="tenancyName" value="Associates">
<div class="row margin-top-10">
<div class="col-xs-3">
<button type="submit" class="btn btn-success uppercase">Log in</button>
</div>
</div>
</form>
<form class="login-form" action="/Account/Login?returnUrl=/Application" name="companyLoginForm" method="post" novalidate="novalidate">
<input type="hidden" name="usernameOrEmailAddress" value="fake#gmail.com">
<input type="hidden" name="password" value="fake">
<input type="hidden" name="rememberMe" value="true">
<input type="hidden" name="companyUrl" value="true">
<input type="hidden" name="tenancyName" value="ALL">
<div class="row margin-top-10">
<div class="col-xs-3">
<button type="submit" class="btn btn-success uppercase">Log in</button>
</div>
</div>
</form>
Post method
[HttpPost]
public virtual async Task<JsonResult> Login(LoginViewModel loginModel, string returnUrl = "", string returnUrlHash = "", bool companyUrl = false)
{
CheckModelState();
// removed for clarity
}
Question : Even though I have press the 2nd submit button,it always send the tenancyName as first submit button's value.That is Asset_Management.Could you tell me why ? Thanks.
Your problem is with the script.
var $loginForm = $('.login-form');
is a collection of all your forms, but
data: $loginForm.serialize(),
will only serialize the first one, so you always posting the vales of the first form. Modify the script to handle the buttons .click() event and get its associated form
$('.btn-success').click(function(e) {
e.preventDefault(); // if you makes the button type="button" this is not required
var form = $(this).closest('.login-form');
if (!form.valid()) {
return;
}
abp.ui.setBusy(
null,
abp.ajax({
contentType: app.consts.contentTypes.formUrlencoded,
url: form.attr('action'),
data: form.serialize()
})
);
});
Why do you even have <form> and <button> at all?
Why not create links in your foreach loop, something like this:
#Html.ActionLink("Login for " + tenant.Name, "LoginAction", new {Id=tenant.Id})
You can style these links all blue and pretty as you like using CSS afterwards.
Update1, you can pass parameters to your controller using the anonymous object. Do you see how I am passing Id? Your Action will need to accept id, see this answer: passing multiple parameters in #html.actionlink()
Update2, passing username and password like this is very bad practice. You are exposing secure credentials to the view. You should forward the user to the login page with username + password input boxes where the user will login.
I have a question about MVC4 (Razor). I have page where I want to filter data. There is a textbox (input) and a submit button. I want to move the text in the textbox to the actionresult. How can I resolve this?
On my page I've the following row:
#{ using (Html.BeginForm("Experiences"))
{
<span class="label">Filter on:</span><input id="FilterText" type="text" size="50"/>
<input type="submit" value="Submit" name="knowledge" /><br />
}
}
<br />
And I want to call the ActionResult Experiences
public ActionResult Experiences(string knowledge = "")
{
ReadExperienceData(knowledge);
return View(ListOfExperiences);
}
Specify the name property value of the input element same as the action method parameter name.
<input id="FilterText" name="knowledge " type="text" size="50"/>
<input type="submit" value="Submit" name="submitKnowledge" />
Also it looks like you are not using the Beginform method properly. You may try any of the below overloads, as needed
#using(Html.Beginform("Knowledge","YourControllerName"))
{
//form elements
}
or
#using(Html.Beginform())
{
//form elements
}
I am using MVC BeginForm with code below, i cannot get the value fpr input controls in my controller. am i doing anytyhing wrong here?
using (Ajax.BeginForm("CreateApp", "App",
new AjaxOptions { UpdateTargetId = "my-modal-dialog", OnBegin = "Dialog.Closing()", OnSuccess = "Dialog.Close()" },
new
{
#class = "appform"
}
))
{
<input id="newAppName" type="text" size="35" value="" />
#Html.TextBoxFor(model => model.Application.AppName);
<input type="submit" value="Start App" class="demo-button ui-state-default ui-corner-all" />
}
My Controller looks like this
[HttpPost]
public ActionResult CreateApp(AppContent app, string newAppName)
{
}
try changing
<input id="newAppName" type="text" size="35" value="" />
to
<input name="newAppName" type="text" size="35" value="" />