I have a razor-pages button tag-helper calling a asp-page-handler that has an asp-route-content parameter that needs to gets it's value from a textarea control within the razor page view on button submit. How can this be accomplished?
Razor view partial code:
<form method="post">
<div class="modal-body">
<textarea id="content" name="content" cols="90" rows="4" placeholder="Comment" required></textarea>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" asp-page="/Post" asp-page-handler="ReplyToComment"
asp-route-blogid="#Model.BlogID" asp-route-parentid="#Model.ID"
asp-route-email="#user.Email" asp-route-author="#author"
asp-route-content="" class="btn btn-primary">Save Reply</button>
</div>
</form>
Razor page handler :
public async Task<IActionResult> OnPostReplyToComment(int blogid,
int parentid, string email, string author, string content)
You need to either bind the textarea content to a Property on your page:
[BindProperty]
public string Content { get; set; }
and use the asp-for tag-helper on the textarea:
<textarea asp-for="Content" cols="90" rows="4" placeholder="Comment" required></textarea>
Or use the [FromForm] attribute in the method signature:
public async Task<IActionResult> OnPostReplyToComment(int blogid,
int parentid, string email, string author, [FromForm] string content)
For more information see MS Docs on Model Binding
Related
I have a button on a GET Form on asp.net core razor pages
<form method="get" asp-page="Index">
<button type="submit" asp-page="Index" asp-page-handler="Something" class="btn btn-primary"></button>
</form>
and the code behind
public IActionResult OnGetSomething(){
//... some code
return Page();
}
My problem is the onget handler code is never executed
If the form is POST the onpost handler will work fine but if it is GET it doesn’t work
So what am I missing here? and how to make the onget handler work?
When you submit a form using GET, the browser trashes query string values in the form action and replaces them with a new query string built from the form fields. You can hit your handler by adding an appropriate hidden field to the form:
<form method="get" asp-page="Index">
<input type="hidden" name="handler" value="Something" />
<button type="submit" class="btn btn-primary">Get</button>
</form>
you can't go to get method because of parameters miss matching.
Suppose:
In controller
[HttpGet]
public IActionResult Create()
{
return View();
}
//Post Method
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Create(string Name)
{
}
In View:
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>]
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
Then it go post method cause it has 1 parameters (Name). if we not net any input or parameters are not same then it hit different method.
It the concept of method overloading
In details of method overloading https://www.geeksforgeeks.org/c-sharp-method-overloading/
How to create object and send it to OnPost in Razor Pages?
<form method="post">
<div>
<label>Add Text</label>
<input asp-for=SentimentData.SentimentText class="form-control" />
<button type="submit" class="btn btn-primary">Save</button>
</div>
</form>
public void OnPost(SentimentData SentimentData)
{
Text = SentimentData.SentimentText;
Analysis.Evaluate(mlContext, Model, SplitDataView.TestSet);
Analysis.UseModelWithSingleItem(mlContext, SentimentData, Model, Text);
}
But after my input field SentimentText is null. i dont know why.
As I understand it from these docs: https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/intro?view=aspnetcore-3.1 , asp-for is used to transfer values from input elements to backend C# class properties, for example:
<input type="text" id="wsite" name="wsite" maxlength="11" asp-for="WebsiteName">
Along with '#folderName ClassName;' at the top, lets you transfer to this example property:
public string WebsiteName { get; set; }
However, testing this out with console.WriteLine show that the property is still null after the form containing the input has been submitted. Any idea what I'm missing?
Edit: Updated to show my property name and asp-for value match, and to add my controller:
[HttpPost]
public IActionResult Post()
{
DBCRUD.Initialize(_context);
return NoContent();
}
The asp-for tag should match the variable-name.
Try defining your html-form like:
#model Classname
<form asp-action="ActionName" asp-controller="ControllerName" ...>
<input type="text" asp-for="VarName">
and your controller:
public MyReturnVariable ActionName(ClassName class) {
Console.WriteLine(class.VarName);
}
The Tag Helpers is used with Model binding and creating and rendering HTML elements(display the model properties) in the web page.
So, in the Web page (or view page), at the top of the header, we should add the following code to assign the model.
#model MVCSample.Models.BookModel
Then, using the following code to display the properties:
<div class="row">
<div class="col-md-4">
<form asp-action="AddBook">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="ID" class="control-label"></label>
<input asp-for="ID" class="form-control" />
<span asp-validation-for="ID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="bookName" class="control-label"></label>
<input asp-for="bookName" class="form-control" />
<span asp-validation-for="bookName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" />
</div>
</form>
</div>
</div>
Code in the controller:
[HttpGet]
public IActionResult AddBook()
{
BookModel book = new BookModel()
{
ID = 1001,
bookName = "War and Peace",
Title = "War and Peace"
};
return View(book);
}
Code in the model:
public class BookModel
{
public int ID { get; set; }
public string bookName { get; set; }
public string Title { get; set; }
}
More details information, you could check the Model Binding.
I'm trying to create a partial view to save on the amount of boilerplate code I need when creating forms. A simple version of what I have is as follows...
#model FormRowViewModel
<div class="form-group row">
<label for="#Model.PropertyName" class="col-lg-2 col-form-label">#Model.Label</label>
<div class="col-lg-10 input-group">
<input type="text" asp-for="#Model.PropertyName" class="form-control">
</div>
</div>
...where FormRowViewModel looks like this...
public class FormRowViewModel {
public FormRowViewModel(string propertyName, string label) {
PropertyName = propertyName;
Label = label;
}
public string PropertyName { get; set; }
public string Label { get; set; }
}
The idea is to use it in a view like this...
#model ContactViewModel
<form method="post" asp-controller="Home" asp-action="Index">
<div asp-validation-summary="All" class="text-danger"></div>
#await Html.PartialAsync("_FormRow", new FormRowViewModel("UserName", "Your name"))
#await Html.PartialAsync("_FormRow", new FormRowViewModel("Email", "Email"))
#await Html.PartialAsync("_FormRow", new FormRowViewModel("Telephone", "Telephone"))
<div class="form-group row">
<div class="offset-sm-2 col-lg-10">
<button type="submit" class="btn btn-primarySubmit</button>
</div>
</div>
</form>
This works, in that it creates the HTML (almost) as expected, but has two problems...
1) The generated HTML includes value attributes that set the content of the textboxes to the property names...
<input type="text" class="form-control" id="PropertyName"
name="PropertyName" value="UserName">
2) Whatever I put in the textboxes, when the form is posted back to the server, the view model properties are all empty strings. Even the property names that were added don't come through.
In case it helps, here is the controller action that handles the view...
public IActionResult Index() =>
View();
[HttpPost]
public IActionResult Index(ContactViewModel vm) {
if (!ModelState.IsValid) {
return View(vm);
}
// Next line added so I can see when it worked
return RedirectToAction(nameof(Privacy));
}
Anyone know what I'm doing wrong? Thanks
Your whole approach here is incorrect. It seems what you're looking for is editor templates. Essentially, you need to create partial views in Views\Shared\EditorTemplates that correspond with types or members of the DataType enum, and add your custom HTML there. For example, you can create a String.cshtml view:
#model string
<div class="form-group row">
<label asp-for="#Model" class="col-lg-2 col-form-label"></label>
<div class="col-lg-10 input-group">
<input asp-for="#Model" class="form-control">
</div>
</div>
Then, for any string property:
#Html.EditorFor(x => x.MyStringProp)
And your custom template will be used, with the proper name binding.
Alternatively, you can create custom taghelpers, but the methodology for that is a bit more complicated, since you'll need to handle the HTML generation in code. If you're interested in that approach, though, look at the source for the built-in tag helpers and create your own based on that.
There is some ViewModel:
class MyViewModel
{
[Required(ErrorMessage = "Field {0} is required")]
public string Email { get; set; }
}
I use jquery validation for front-end:
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validate/1.16.0/jquery.validate.min.js">
</script>
<script src="https://ajax.aspnetcdn.com/ajax/jquery.validation.unobtrusive/3.2.6/jquery.validate.unobtrusive.min.js">
</script>
The fragment of Razor markup:
<form asp-controller="Account" asp-action="Register" role="form">
<div class="form-group">
<div asp-validation-summary="All" class="text-danger"></div>
</div>
<div class="form-group">
<label asp-for="Email"></label>
<input asp-for="Email" class="form-control" aria-describedby="email" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
</form>
The issue is validation is triggered immediately when user get the html page. So one sees error for email field when she inputs nothing yet (Field Email is required). How can I prevent this behavior (triggered on submit)?
There is action:
public IActionResult SomeAction(MyViewModel model = null)
{
return View(model);
}
i.e. controller pass to action null model (value by default). It is the reason of that behavior of jquery validation