This is my form:
#using (Html.BeginForm())
{
<h3 class="text-blue title-article editable">thisStr</h3>
<input type="submit" value="xxxx" class="btn btn-success" name="xxxx"/>
}
#model.title is part of an inline-editable that i can change to whatever, what i need to do is
pass the string in the h3 to this controller-method:
public ActionResult method(string test)
{
someProp = test;
return View();
}
I think my problem is this line:
<input type="submit" value="xxxx" class="btn btn-success" name="xxxx"/>
Can someone help me out, thanks!
Put this in the form:
#Html.HiddenFor(x=>x.Title)
view:
#using (Html.BeginForm("YourAction","YourController",FormMethod.Post))
{
<h3 class="text-blue title-article editable">#Model.Title</h3>
#Html.HiddenFor(x=>x.Title)
<input type="submit" value="xxxx" class="btn btn-success" name="xxxx"/>
}
in your action:
[HttpPost]
public ActionResult YourAction(FormCollection form)
{
sting vl= form["Title"].ToString();
return View();
}
Add a #Html.HiddenFor((p) => Model.Title) inside your form, which will then submit the text back with the POST for you.
Related
I have the following form in a .NET Core application, consisting of a text input field and a "Submit" button.
I'd like the text from the text input field to re-appear in the form after submission, being passed to the controller action from the form and then being passed back to the view.
However, when I test the application, although the inputted values from the view appear when they are bound to the model in the controller, when they are passed back to the view they are wiped and I receive an "Object reference set to null" exception error.
I wondered if there's something missing from my code or what the potential cause of this may be?
Any advice would be great here,
Thanks,
Robert
// This is my view, featuring a simple form
// Values from the view are successfully being passed into the Controller
// This is the exception I receive when the values are passed back to the view:
My code:
#page
#model Models.StringModel
<div class="text-left">
<form asp-controller="Home" asp-action="Alter">
<span class="form-control">
<label asp-for="Name">Alter string:</label>
#if (#Model != null)
{
<input type="text" asp-for="Name" class="changeString" value="#Model.Name"/>
} else
{
<input type="text" asp-for="Name" class="changeString"/>
}
<input class="btn btn-primary" type="submit" value="Update" action="Update" />
</span>
</form>
</div>
StringModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace SplitString.Models
{
public class StringModel
{
public int ID { get; set; }
public string Name { get; set; }
}
}
HomeController.cs
using Microsoft.AspNetCore.Mvc;
using SplitString.Models;
using System.Threading.Tasks;
namespace SplitString.Controllers
{
public class HomeController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Alter([Bind("Id, Name")] StringModel stringModel)
{
stringModel.ID = 1;
return View("~/Pages/Index.cshtml", stringModel);
}
}
}
Thanks,
Robert
It looks like you are using a razor page project,so that you don't need to use mvc in it.You only need to use page handler:
Index.cshtml:
#page
#model IndexModel
<div class="text-left">
<form method="post">
<span class="form-control">
<label asp-for="stringModel.Name">Alter string:</label>
#if (#Model != null)
{
<input type="text" asp-for="stringModel.Name" class="changeString" value="#Model.stringModel.Name"/>
} else
{
<input type="text" asp-for="stringModel.Name" class="changeString"/>
}
<input class="btn btn-primary" type="submit" value="Update" action="Update" />
</span>
</form>
</div>
Index.cshtml.cs:
public class IndexModel : PageModel
{
private readonly ILogger<IndexModel> _logger;
[BindProperty]
public StringModel stringModel { get; set; } = new StringModel();
public IndexModel(ILogger<IndexModel> logger)
{
_logger = logger;
}
public void OnGet()
{
}
public void OnPost()
{
stringModel.ID = 1;
//you can do something here
}
}
result:
By looking at this part of your code:
#if (#Model != null)
{
<input type="text" asp-for="Name" class="changeString" value="#Model.Name"/>
}
I saw that you are trying to access the Name property without checking if it has any value.
If you change your code to this it shouldn't throw an exception anymore.
#if (#Model != null && !string.IsNullOrEmpty(Model.Name))
{
<input type="text" asp-for="Name" class="changeString" value="#Model.Name"/>
}
please remove #page from your .cshtml file.
If you use View Engine to render cshtml, please don't use #page.
If you want to use #page, please use razor pages.
// #page
#model Models.StringModel
<div class="text-left">
<form asp-controller="Home" asp-action="Alter">
<span class="form-control">
<label asp-for="Name">Alter string:</label>
#if (#Model != null)
{
<input type="text" asp-for="Name" class="changeString" value="#Model.Name"/>
} else
{
<input type="text" asp-for="Name" class="changeString"/>
}
<input class="btn btn-primary" type="submit" value="Update" action="Update" />
</span>
</form>
</div>
I'm not able to get ReturnUrl to work on HttpPost using ASP.NET Core 6 MVC.
When adding a breakpoint to the POST method, returnurl is always null. But with .NET 5, it works with the same code setup except that with .NET 6, I need to make the returnurl parameter nullable so that I won't get an error "returnurl field is required".
This is the code I'm using - any help would be much appreciated.
Thanks.
Model:
namespace IdentityManagerDotNet6.Models
{
public class LoginViewModel
{
[Required]
[EmailAddress]
public string Email { get; set; } = string.Empty;
[Required]
[DataType(DataType.Password)]
public string Password { get; set; } = string.Empty;
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
}
Controller
[HttpGet]
public IActionResult Login(string? returnurl)
{
ViewData["ReturnUrl"] = returnurl;
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel loginViewModel, string? returnurl)
{
ViewData["ReturnUrl"] = returnurl;
returnurl = returnurl ?? Url.Content("~/");
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(loginViewModel.Email, loginViewModel.Password, loginViewModel.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
return LocalRedirect(returnurl);
}
if (result.IsLockedOut)
{
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(loginViewModel);
}
}
return View(loginViewModel);
}
View:
#model LoginViewModel
<h1 class="text-info">Log in</h1>
<div class="row">
<div class="col-md-8">
<form asp-controller="Account" asp-action="Login" asp-route-returnurl="#ViewData["ReturnUrl"]" method="post" role="form">
<h4>Use a local account to log in</h4>
<hr />
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="Email" class="col-md-2"></label>
<div class="col-md-10">
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</div>
<div class="form-group mt-3">
<label asp-for="Password" class="col-md-2"></label>
<div class="col-md-10">
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
</div>
<div class="form-check mt-3">
<input class="form-check-input" asp-for="RememberMe" type="checkbox" value="" id="flexCheckChecked">
<label class="form-check-label" asp-for="RememberMe" for="flexCheckChecked">
Remember me?
</label>
</div>
<div class="form-group">
<div class=" col-1 my-3">
<button type="submit" asp-controller="Account" asp-action="Login" class="btn btn-success form-control">Login</button>
</div>
</div>
<p>
<a asp-action="Register">Register as a new user?</a>
</p>
<p>
<a asp-action="ForgotPassword">Forgot your passord?</a>
</p>
</form>
</div>
</div>
"I'm not able to get ReturnUrl to work on HttpPost using ASP.NET Core 6 MVC.":
I have checked your code between the line. It doesn't has anything
wrong with [FromQuery] So you don't need to do anything on [FromQuery] as other answer I've seen, may be deleted now.
Issue Replication:
I have reproduced your issue successfully as you can see below:
What Causing the Issue:
If you investigate your code again you would noticed that you are
using asp-controller="Login" asp-action="Login" twice on your
Login.cshtml at the begining of the form and at the point of submit button this causing the data loss while you are submitting the form.
At the starting on form:
<form asp-controller="Login" asp-action="Login" asp-route-returnurl="#ViewData["ReturnUrl"]" method="post" role="form">
At your button submit::
<button type="submit" asp-controller="Login" asp-action="Login" class="btn btn-success form-control">Login</button>
Solution:
The easiest solution is just modify your submit button code like below which will resolve your issue:
<div class="form-group">
<div class=" col-1 my-3">
<button type="submit" class="btn btn-success form-control">Login</button>
</div>
</div>
Output:
Hope it will resolve your returnurl null issue completely.
Controller
[HttpGet]
public IActionResult Login(string? returnurl) <-- you don't need it
{
ViewData["ReturnUrl"] = returnurl; <-- you don't need it
return View();
}
View
<form method="post" role="form"> <-- you can do that and the returnUrl
will be posted to you anyway
Or
<form method="post" role="form" new { returnUrl = Context.Request.QueryString["ReturnUrl"]} >
it will work either way
I have come across a weird issue, I hope someone can explain why the following is happening.
My controller:
MasterModel main = new MasterModel();
public ActionResult Index()
{
return View();
}
[HttpGet]
public ActionResult VehicleDetail()
{
pageSessionSetup();
return PartialView("VehicleDetail", main.Vehicle);
}
[HttpPost]
public ActionResult VehicleDetail(VehicleDetailDisplay model)
{
ModelState.AddModelError("", "Errors occured");
main.Vehicle = model;
pageSessionSetup();
return PartialView("VehicleDetail", main.Vehicle);
}
Updated With View
My View:
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
#using (Ajax.BeginForm("VehicleDetail", "Operator", null, new AjaxOptions
{
UpdateTargetId = "VehicleDetail",
InsertionMode = InsertionMode.Replace,
HttpMethod = "Post"}, new { id = "VehicleDetail" }))
{
#Html.Partial("_ValidationSummary", ViewData.ModelState)
<div class="panel panel-default panel-body">
...
</div>
<div class ="col-lg-7 col-md-7 col-sm-7 col-xs-7 row">
<button type="submit" value="Save" class="btn btn-lg btn-green col-lg-2 col-md-5 col-sm-7 col-xs-7">Save</button>
</div>
}
And on my partial view I have a submit button, but when I click the submit button one time then the form gets submitted more than one time.
UPDATE:
use Html.BeginForm("ActionName", "ControllerName", FormMethod.Post) instead of Ajax.BeginForm() OR check if you have included the jquery.unobtrusive-ajax.min.js twice in your page(s)(in partial views also).
--------------------------------------------------------------------------------------------------------
#using (Html.BeginForm("ActionName", ""ControllerName", FormMethod.Post))
{
<label>SomeLabel</label>
...
<input type="submit" value="Button" /></p>
}
This is my form
#using (Html.BeginForm("EditPayments", "BookingPathLabelsCms"))
{
if (#Model.DisplayName == "Payment Labels")
{
<textarea id="seeit" name="seeit" rows="5" cols="10"></textarea>
<textarea id="seeitNoSelect" name="seeitNoSelect" rows="5" cols="10"></textarea>
<div class="cmsButtonContainer">
Cancel it
<input type="submit" name="Save" value="Save it"#* onmouseover="copyto();"*# />
</div>
}
}
And this is my controller action
public ActionResult EditPayments(BookingPathLabelsCmsViewModel model)
{
string txtarea = Request.Form["seeit"];
return RedirectToAction("Index");
}
Am not getting the values of textareas here,but values in the breakpoint ,see image.
Your code should looks like:
#using (Html.BeginForm("EditPayments", "BookingPathLabelsCms"))
{
if (#Model.DisplayName == "Payment Labels")
{
#Html.TextBoxFor(m => m.SeeIt)
#Html.TextBoxFor(m => m.SeeItNoSelect)
<div class="cmsButtonContainer">
Cancel it
<input type="submit" name="Save" value="Save it"#* onmouseover="copyto();"*# />
</div>
}
}
Of course, your ViewModel BookingPathLabelsCmsViewModel should have SeeIt and SeeItNoSelect properties. After that, MVC will bind correctly entered data.
First create a class with property.
public class TextAreaProperty
{
public string MyTextAreaValue { get; set; }
}
Use on the view declare like:
#model <project_name>.Models.<Class_name>
In this case:
#model MvcApplication1.Models.TextAreaProperty
Use this textArea Razor
#Html.TextAreaFor(x=> x.MyTextAreaValue)
On method post receiving parameter type TextAreaProperty
[HttpPost]
public ActionResult Index(TextAreaProperty textAreaProperty)
{
return View();
}
You will get the value from textAreProperty.
I have a problem to send my Model into my controller.
I use a button with the ajax to change the page but i need the model who is the first page to the second page.
I would like send my model in my controller but it's not work.
When i come in the page CreateAll, the renderpartial follow works to display Step1 but if i click on the step2 i would like the mainModel to be send to my controller use a partial view with submodel.
My model is:
public class CreateAllStep
{
public CreateStep1 Step1 { get; set; }
public CreateStep2 Step2 { get; set; }
public CreateAllStep(CreateStep1 step1, CreateStep2 step2)
{
this.Step1 = step1;
this.Step2 = step2;
}
}
My controller is(when the page start):
public ActionResult Create()
{
CreateStep1 step1=FillStep1();
CreateStep2 step2 = FillStep2();
CreateAllStep allStep = new CreateAllStep(step1, step2);
return View(allStep);
}
My controller is(when i click on the button, it's here where i would like send the model):
[HttpPost]
public ActionResult Create(String btn, CreateAllStep form)
{
if (Request.IsAjaxRequest())
{
if (btn != null)
{
if (btn == "Step1")
{
return PartialView("Step1",form.Step1);//not work
}
else if (btn == "Step2")
{
return PartialView("Step2");//work
}
else if(btn =="AllStep")
{
return PartialView("AllStep");
}
}
}
return View();
}
And my main view is :
#model SiteWebEmpty.Models.CreateAllStep
#{
ViewBag.Title = "Title";
}
<script type="text/javascript">
$(function () {
$('form').submit(function () {
$.post(this.action, $(this).serialize(), function (data) {
alert(data);
});
return false;
});
});
</script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
<h2>Title</h2>
#using (Ajax.BeginForm("Create", //controller action name
"CreateStep", //controller name
new AjaxOptions //ajax options that tell mvc how to perform the replacement
{
UpdateTargetId = "ViewPage", //id of div to update
HttpMethod = "Post" //how to call the controller action
}, new { id = "FormName" }))
{
#Html.ValidationSummary(true)
<fieldset>
<legend>Create </legend>
<button type="submit" name="btn" value="Step1" id="Step1">Step 1</button>
<button type="submit" name="btn" value="Step2" id="Step2">Step 2</button>
<button type="submit" name="btn" value="AllStep" id="AllStep">All Step</button>
<div id="ViewPage">
#Html.Partial("Step1", Model)
</div>
</fieldset>
}
My partial view is:
#model SiteWebEmpty.Models.ArticleRequest.CreateArticle.ArticleRequestDisplayCreateAllStep
<fieldset>
<legend>Step 1</legend>
#Html.LabelFor(step1 => step1.Step1.Customer)
#Html.EditorFor(step1 => step1.Step1.Customer)
#Html.ValidationMessageFor(step1 => step1.Step1.Customer)
#Html.LabelFor(articleType => articleType.Step1.ArticleType)
#Html.DropDownList("ArticleType", Model.Step1.ArticleType)
#Html.ValidationMessageFor(articleType => articleType.Step1.ArticleType)
#Html.LabelFor(model => model.Step1.LabelType)
#Html.DropDownList("LabelType", Model.Step1.LabelType)
#Html.ValidationMessageFor(model => model.Step1.LabelType)
</fieldset>
render html:
<script src="/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
<h2>Title</h2>
<form action="/CreateStep/Create?Length=13" data-ajax="true" data-ajax-method="Post" data-ajax-mode="replace" data-ajax-update="#ViewPage" id="FormName" method="post"> <fieldset>
<legend>Create </legend>
<button type="submit" name="btn" value="Step1" id="Step1">Step 1</button>
<button type="submit" name="btn" value="Step2" id="Step2">Step 2</button>
<button type="submit" name="btn" value="AllStep" id="AllStep">All Step</button>
<div id="ViewPage">
<fieldset>
<legend>Step 1</legend>
<label for="Customer">Customer</label>
<input class="text-box single-line" data-val="true" data-val-required="Customer is required" id="Customer" name="Customer" type="text" value="" />
<span class="field-validation-valid" data-valmsg-for="Customer" data-valmsg-replace="true"></span>
<label for="ArticleType">Article Type</label>
<select data-val="true" data-val-required="ArticleType is required" id="ArticleType" name="ArticleType"><option value="127">AR1 : New Product</option>
<option value="161">AR2 : Product Modification</option>
</select>
<span class="field-validation-valid" data-valmsg-for="ArticleType" data-valmsg-replace="true"></span>
<label for="LabelType">Label Type</label>
<select data-val="true" data-val-required="LabelType is required" id="LabelType" name="LabelType"><option value="129">Private Label</option>
</select>
<span class="field-validation-valid" data-valmsg-for="LabelType" data-valmsg-replace="true"></span>
</fieldset>
</div>
</fieldset>
</form>
Thanks for your help :) !
Could you post the final HTML?
I think that your #Html.Partial("Step1", Model.Step1) will render a input text with id like Customer or ArticleType instead of Step1.Customer and Step1.ArticleType. What will bind to CreateAllStep.Customer that doesn´t exist.
If you have the Headers sent by the browsers will help too.
Update: Change your partial Step1, to accept a CreateAllStep Model and try again
Try removing your constructor on your ViewModel:
public CreateAllStep(CreateStep1 step1, CreateStep2 step2)
{
this.Step1 = step1;
this.Step2 = step2;
}
And change the controller code to:
public ActionResult Create()
{
CreateAllStep allStep = new CreateAllStep{Step1 = FillStep1(), Step2 = FillStep2()};
return View(allStep);
}
I have run into issues with constructors with parameters when databinding.