Razor pages, detect text changes in textview - asp.net-mvc

I have a razor page where the user can make some options from a dropdownlist and than enter some value.
See attached image
What i want to achieve is that as user change any of the textboxes, call the appropriate handler function.
So as soon user enter some value in the textfield 1, the one to the right of textlabel "Some value" i want to do some calculation and update the textfield 2, the one to the right of textlabel "Some other value" . And vice versa for the other textfield.
I have following code
#page
#model CurrencyConverter.Pages.ConvertModel
#{
ViewData["Title"] = "Convert";
}
<div>
#if (!string.IsNullOrEmpty(Model.ResultInfo))
{
<p>#Model.ResultInfo</p>
}
</div>
<form method="post">
<div>
#Html.DropDownListFor(m => m.CurencyModel.FirstCurrency, new SelectList(Model.Options, "Value", "Text"), "Select currency", new { #class = "css-class" })
<input asp-for="CurencyModel.TotalAmountFirstCurrency" />
</div>
<div>
#Html.DropDownListFor(m => m.CurencyModel.SecondCurrency, new SelectList(Model.Options, "Value", "Text"), "Select currency", new { #class = "css-class" })
<input asp-for="CurencyModel.TotalAmounSecondCurrency" />
</div>
<div>
<button type="submit" asp-page-handler="FirstCurrency">Submit first currency</button>
<button type="submit" asp-page-handler="SecondCurrency">Submit second currency</button>
</div>
</form>
the cshtml.cs file looks like this
public class ConvertModel : PageModel
{
[TempData]
public string ResultInfo { get; set; }
[BindProperty]
public CurrencyModel CurencyModel { get; set; }
[BindProperty]
public IEnumerable<SelectListItem> Options
{
get; set;
}
public ConvertModel()
{
//initalization
}
public async Task<IActionResult> OnPostFirstCurrency()
{
if(!ModelState.IsValid)
{
return Page();
}
//given first currency calculate the second from the first using some formula
}
public async Task<IActionResult> OnPostSecondCurency()
{
if (!ModelState.IsValid)
{
return Page();
}
//given second currency calculate the second from the first using some formula
}
}
what i want to achieve is in
<div>
#Html.DropDownListFor(m => m.CurencyModel.SecondCurrency, new SelectList(Model.Options, "Value", "Text"), "Select currency", new { #class = "css-class" })
<input asp-for="CurencyModel.TotalAmounSecondCurrency" onchanged=asp-page-handler="FirstCurrency"/>
But this seems not possible with only pure razor and c# syntax.

Related

how can i assign value to textbox in MVC - Sharepoint Provider-hosted

I want to get and assign value to my textbox from controller.
here is my textbox:
<input type="text" class="form-control" id="RegardingTo" name="RegardingTo" value="??????"/>
then i want to get the value from this action.
public ActionResult Edit(int? RequestID)
{
if (RequestID <= 0)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var ReqID = db.usp_RequestGetDetails(RequestID);
if (ReqID == null)
{
return HttpNotFound();
}
return View();
}
please help :)
Yes you can assign value to the textbox using Model, First of all create a model then link that model with your view. And In Controller assign the value to model and return to the view.
Or At runtime if you want to assign the value to your text box then you can use Ajax call to your controller and get the value.
Please revert in case of any query.
See what i am doing to do the same, Make a custom model with your relevant fields, then assign values to them in controller, and pass this values to View, And that's it. :)
Custom Model
public partial class QuoteParameter
{
public Nullable<System.DateTime> TripStartDateLimit { get; set; }
public Nullable<System.DateTime> TripEndDateLimit { get; set; }
public int PolicyId { get; set; }
}
Controller
public ActionResult Index()
{
QuoteParameter quote = new QuoteParameter();
quote.TripEndDateLimit = DateTime.Now;
quote.TripEndDateLimit = DateTime.Now;
quote.PolicyId = 5;
return View(quote);
}
View
#model EHIC.Models.Models.QuoteParameter
By Razor syntax
<div class="row-fluid span12">
<div class="span4">
<p><strong>Trip Start Date Limit :</strong></p>
</div>
<div class="span5">
#Html.TextBoxFor(model => model.TripStartDateLimit, "{0:dd/MM/yyyy}", new { #class = "form-control", #placeholder = "Policy StartDate Limit", #required = true })
</div>
</div>
<div class="row-fluid span12">
<div class="span4">
<p><strong>Trip End Date Limit :</strong></p>
</div>
<div class="span5">
#Html.TextBoxFor(model => model.TripEndDateLimit, "{0:dd/MM/yyyy}", new { #class = "form-control", #placeholder = "Policy EndDate Limit", #required = true })
</div>
</div>
By HTML Code
<input type="text" class="form-control" id="TripStartDateLimit" name="TripStartDateLimit" value="#Model.TripStartDateLimit"/>
<input type="text" class="form-control" id="TripEndDateLimit" name="TripEndDateLimit" value="#Model.TripEndDateLimit"/>
EDIT
By Click on this button you can send the PolicyId(as an example) to controller, and then you can do whatever you want there..!!!
<a href='../../controller/Edit?PolicyId=#Models.PolicyId'>
<span title='Edit'></span>
</a>
#Html.ActionLink("Edit","Edit", new { id = item.RequestID })
You can find the PolicyId which you sent from the Edit Page..
public ActionResult Edit(int id)
{
//Get your data from Store_procedure..
return View();
}

"Required" attribute not working when "AllowHtml" attribute is used. MVC 5

I want to post a html with a wysiwyg editor so I used [AllowHtml] attribute on my property. It works, but when I use it with [Required] and [StringLength] attributes, it stops working. ModelState.IsValid returns true even if prop is empty.
Yes, I know I can manually control it if it is null and add an error to ModelState, but why?
Why this happens? Is there a better way to post some HTML code to back-end?
My dto:
public int Id { get; set; }
[Required(ErrorMessage = CErr.RequiredField)]
[StringLength(100, ErrorMessage = CErr.Min5Max100)]
[MinLength(5, ErrorMessage = CErr.Min5Max100)]
public string Name { get; set; }
[AllowHtml]
[Required(ErrorMessage = CErr.RequiredField)]
[StringLength(4000, ErrorMessage = CErr.TooLongValue)]
public string HtmlBody { get; set; }
My action:
[Route("new")]
[HttpPost]
public ActionResult NewMessageLayout(ManageMessageLayoutDto model)
{
if (ModelState.IsValid)
{
var response = Repositories.MessageLayoutRepository.SaveMessageLayout(model, CurrentUser.Id);
if (response.Status == ResultStatus.Success)
{
return RedirectToAction("MessageManagement");
}
else
{
ModelState.AddModelError("error", response.Message);
return View("ManageMessageLayout", model);
}
}
return View("ManageMessageLayout", model);
}
And some HTML:
#using (Html.BeginForm())
{
#Html.HiddenFor(m => m.Id)
<label>Name <span class="req">*</span></label>
#Html.TextBoxFor(m => m.Name, new { #class = "form-control" })
#Html.ValidationMessageFor(m => m.Name, null, new { #class = "label label-danger" })
<label>Content <span class="req">*</span></label>
#Html.TextBoxFor(m => m.HtmlBody)
#Html.ValidationMessageFor(m => m.HtmlBody, null, new { #class = "label label-danger" })
<input class="btn btn-success btn-block btn-lg" type="submit" value="#(editing ? "Save" : "Add")" />
}
I am unable to replicate your error. However, I did notice a few things. First, according to the ckEditor documentation, textbox is not a valid attaching point for the editor. You should use textarea.
CkEditor Developer Documentation
At this point any textarea, p, or div element can be transformed into
a rich text editor by using the ckeditor() method.
Next, notice that I added AllowEmptyStrings=false to the [Required( attribute. This may be the important piece you are missing (will test without) - Testing seems to indicate that not setting AllowEmptyStrings does not impact the results of this test setup as the default value for this property is false. The model was still invalid.
Setup
VS 2015, MVC 5.2.2, .NET 4.5.1, jQuery 1.10.2, ckEditor 3.6.4
View Model
public class TestViewModel
{
[AllowHtml]
[Required(AllowEmptyStrings = false, ErrorMessage = "This should be filled out")]
[StringLength(4000, ErrorMessage="Its too big")]
public string HtmlBody { get; set; }
}
Controller Actions
public ActionResult About()
{
return View(new TestViewModel());
}
[HttpPost]
public ActionResult About(TestViewModel model)
{
if (!ModelState.IsValid) throw new Exception();
var test = model.HtmlBody;
return RedirectToAction("Contact");
}
View
#model WebApplication6.Models.TestViewModel
#{
ViewBag.Title = "About";
}
<h2>Test of HTML</h2>
#using (Html.BeginForm())
{
<label>Content <span class="req">*</span></label>
#Html.TextAreaFor(m => m.HtmlBody)
#Html.ValidationMessageFor(m => m.HtmlBody, null, new { #class = "label label-danger" })
<input type ="submit" value="test on server"/>
}
#section scripts
{
<script type="text/javascript">
$(function () {
$('#HtmlBody').ckeditor();
});
</script>
}
Results:
Basically, the exception was thrown because the model state was invalid
I found the problem.
My presentation layer was using 5.2.2.0 version of System.Web.Mvc but repository layer was using 5.2.3.0. I downgraded this to 5.2.2.0. And now it is working normally.

Losing form values after validation

Using a ViewModel for validation:
public class CCvm
{
[Required(ErrorMessage = "Please enter your Name")]
public string cardHolderName { get; set; }
}
My controller calls a task on post:
public async Task<ActionResult> Pay(FormCollection form, CCvm model)
{
if (!ModelState.IsValid)
{
return View(model);
}
}
And the View:
#model GCwholesale.Models.CCvm
#{
Layout = "~/Views/Shared/_HomeSubPageLayout.cshtml";
ViewBag.Title = "Secure Checkout";
}
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
<div class="Payment">
<label>Name on Card: </label>
#Html.EditorFor(model => model.cardHolderName, new { htmlAttributes = new { #placeholder = "Cardholder Name Please", #Value = ViewBag.Name } })<br />
#Html.ValidationMessageFor(model => model.cardHolderName)
<button class="submitCheckout">SUBMIT NOW</button>
</div>
}
But when validation fails the data in the form goes away.
Thanks for taking a look.
You do not need to set #Value = ViewBag.Name inside EditorFor.
#Html.EditorFor(model => model.cardHolderName,
new { htmlAttributes = new { #placeholder = "Cardholder Name Please" } })
Besides, you do not need FormCollection as a parameter because you already have CCvm Model.
public async Task<ActionResult> Pay(CCvm model){
{
//...
}
#Value = ViewBag.Name
You're not setting the ViewBag.Name, so it wouldn't have a value and would result in a blank input. Remove that and let the HtmlHelper set it based off the value in the posted model.

MVC4: Two radio buttons for a single boolean model property

I'm attempting to find the correct Razor syntax for mutually exclusive radio buttons that both reflect the value of a boolean property on my model. My model has this:
public bool IsFemale{ get; set; }
I would like to display this with two radio buttons, one "Male" and the other "Female," but everything I've tried so far has not reflected the actual value of the IsFemale property on the model. Currently, I have this:
#Html.RadioButtonFor(model => model.IsFemale, !Model.IsFemale) Male
#Html.RadioButtonFor(model => model.IsFemale, Model.IsFemale) Female
This seems to persist the value correctly if I change and update, but does not mark the correct value as checked. I'm sure this is something stupid, but I'm stuck.
Try like this:
#Html.RadioButtonFor(model => model.IsFemale, "false") Male
#Html.RadioButtonFor(model => model.IsFemale, "true") Female
And here's the full code:
Model:
public class MyViewModel
{
public bool IsFemale { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel
{
IsFemale = true
});
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return Content("IsFemale: " + model.IsFemale);
}
}
View:
#model MyViewModel
#using (Html.BeginForm())
{
#Html.RadioButtonFor(model => model.IsFemale, "false", new { id = "male" })
#Html.Label("male", "Male")
#Html.RadioButtonFor(model => model.IsFemale, "true", new { id = "female" })
#Html.Label("female", "Female")
<button type="submit">OK</button>
}
In MVC 6 (ASP.NET Core) this can also be achieved with tag helpers:
<label>
<input type="radio" asp-for="IsFemale" value="false" /> Male
</label>
<label>
<input type="radio" asp-for="IsFemale" value="true" /> Female
</label>
As far as September 2022.
Boolean radio button using: .NET Framework 4.7.2, MVC 5.2.7, Bootstrap 5.1.3.
Model
public class TheViewModel
{
public bool IndustrialDegree { get; set; }
}
View
<div class="col-4 col-md-2 mb-3">
#Html.Label("Industrial Degree", new { #class = "d-block form-label" })
<div class="btn-group d-flex" role="group" aria-label="Basic radio toggle button group">
#Html.RadioButtonFor(Model => Model.IndustrialDegree, true, new { #class = "btn-check", #id = "IndustrialDegreeTrue" })
#Html.Label("IndustrialDegreeTrue", "Yes", new { #class = "btn btn-outline-primary" })
#Html.RadioButtonFor(Model => Model.IndustrialDegree, false, new { #class = "btn-check", #id = "IndustrialDegreeFalse" })
#Html.Label("IndustrialDegreeFalse", "No", new { #class = "btn btn-outline-primary" })
</div>
</div>
Notice that I'm returning a pure boolean value to the controller.
Result
It works in both directions.
This is what you'll see on the controller when debugging the view model.
and

how to select dropdownlist value and display in mvc3?

I have an MVC3 web application. On index.cshtml I have two dropdown lists. When I select from those lists I need to click on a next button and I want to display the selected values. How can i do this?
homecontroller.cs
DataRepository objRepository = new DataRepository();
public ActionResult Index()
{
ViewModel objViewModel = new ViewModel();
objViewModel.ID = objRepository.GetPricingSecurityID();
objViewModel.ddlId = objRepository.GetCUSIP();
return View(objViewModel);
}
ViewModel.cs
public class ViewModel
{
//DDL ID
[Required(ErrorMessage = "Please select a PricingSecurityID")]
public List<SelectListItem> ddlId { get; set; }
//DropDownList Values
[Required(ErrorMessage = "Please select a PricingSecurityID")]
public List<SelectListItem> ID { get; set; }
}
index.cshtml
<div class="editor-label">
#Html.Label("Pricing SecurityID")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.ID,
new SelectList(Model.ID, "Value", "Text"),
"-- Select category --"
)
#Html.ValidationMessageFor(model => model.ID)
</div>
<div class="editor-label">
#Html.Label("CUSIP ID")
</div>
<div class="editor-field">
#Html.DropDownListFor(model => model.ddlId,
new SelectList(Model.ddlId, "Value", "Text"),
"-- Select category --"
)
#Html.ValidationMessageFor(model => model.ddlId)
</div>
<p>
<input type="submit" value="Next" />
</p>
How can I display selected values?
If your requirement is to build some kind of wizard, you need a way of maintaining state between steps.
ViewBag is no good for this because you should be following the PRG (Post/Redirect/Get) pattern for each wizard step.
TempData would work for navigating forward between steps but will fall over if the user goes back or navigates to a step directly.
You therefore need something with a longer lifetime. The ASP.NET Session object or a database are both good candidates for this.
Here's an example:
public class WizardController : Controller
{
public ActionResult Step1()
{
var session = GetWizardSession();
if (session.Step1 == null)
{
session.Step1 = new Step1View
{
PricingSecurityIds = new SelectList(new[] { 1, 2, 3, 4, 5 }),
SomeOtherIds = new SelectList(new[] { 1, 2, 3, 4, 5 })
};
}
return View(session.Step1);
}
[HttpPost]
public ActionResult Step1(Step1View cmd)
{
var session = GetWizardSession();
// save the wizard state
session.Step1.SelectedPricingSecurityId = cmd.SelectedPricingSecurityId;
session.Step1.SelectedSomeOtherId = cmd.SelectedSomeOtherId;
// now onto step 2
session.Step2 = new Step2View
{
PricingSecurityId = cmd.SelectedPricingSecurityId,
SomeOtherId = cmd.SelectedSomeOtherId,
Name = "John Smith"
};
return RedirectToAction("step2");
}
public ActionResult Step2()
{
return View(GetWizardSession().Step2);
}
public WizardSession GetWizardSession()
{
var session = Session["wizardsession"];
if (session == null)
{
session = new WizardSession();
Session["wizardsession"] = session;
}
return session as WizardSession;
}
}
public class Step1View
{
public SelectList PricingSecurityIds { get; set; }
public SelectList SomeOtherIds { get; set; }
public int SelectedPricingSecurityId { get; set; }
public int SelectedSomeOtherId { get; set; }
}
public class Step2View
{
public int PricingSecurityId { get; set; }
public int SomeOtherId { get; set; }
public string Name { get; set; }
}
public class WizardSession
{
public Step1View Step1 { get; set; }
public Step2View Step2 { get; set; }
}
In Step1 we make a call to GetWizardSession. This returns an object from the ASP.NET Session that contains all of the information we have collected for each step in the wizard. In this example we simply store the ViewModel for each step (i.e. session.Step1).
We check to see if Step1 exists in the session and create it if it doesn't. We then pass the Step1 model to our view.
When the user submits the form we update the "Selected" values in session.Step1. This ensures that if the user navigates back to /step1, we "remember" their values. We then build the model for Step2 and save it in the session.
When we navigate to /step2 we assume that a model exists in the session (because they should have got here from step1) so we just return return View(GetWizardSession().Step2);
The views:
Step 1
#model MvcWizardDemo.Controllers.Step1View
#{
ViewBag.Title = "Step1";
}
<h2>Step1</h2>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
#using (Html.BeginForm()) {
#Html.ValidationSummary(true)
<fieldset>
<legend>Step1View</legend>
<div class="editor-label">
#Html.LabelFor(m => m.PricingSecurityIds)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.SelectedPricingSecurityId, Model.PricingSecurityIds)
#Html.ValidationMessageFor(m => m.PricingSecurityIds)
</div>
<div class="editor-label">
#Html.LabelFor(m => m.SomeOtherIds)
</div>
<div class="editor-field">
#Html.DropDownListFor(m => m.SelectedSomeOtherId, Model.SomeOtherIds)
#Html.ValidationMessageFor(m => m.SomeOtherIds)
</div>
<p>
<input type="submit" value="Next" />
</p>
</fieldset>
}
Step 2
#model MvcWizardDemo.Controllers.Step2View
#{
ViewBag.Title = "Step2";
}
<h2>Step2</h2>
Hi, #Model.Name you selected the following values in the previous step:
<p>
<strong>Security Id:</strong> #Model.PricingSecurityId
</p>
<p>
<strong>Some other Id:</strong> #Model.SomeOtherId
</p>
Try this it should work :
[HttpPost]
public ActionResult Index(ViewModel model)
{
// put what you want to show
}

Resources