How to post to a Razor PageModel from partial view? - asp.net

I'm building a website which has modal login and registrations forms.
The issue is when I'm trying to submit the form filled by the user, the OnPost of the corresponding razor models are not being called. I also tried using the Identity models as the models for the views and those are not being called as well.
Is there a way to do this correctly?

In your Partial view you need to point the form to the page which has the OnPost handle.
<form asp-page="/YourPage" method="post">
...inputs...
<button type="submit">Submit</button>
</form>
Make sure your OnPost accepts a a parameter of the view model like so:
OnPost(MyViewModel vm)
Realised you came after this question
Assuming you have the LoginViewModel as a property inside your razor page.
Instead of using
<partial name="_LoginPartial"
model='new LoginViewModel { InputModel = new InputModel() }' />
you want to use
<partial name="_LoginPartial" for='LoginViewModel' />

Related

Razor / Blazor page - form & validation without navigation

I have a razor page with a form, this one is attached to a model.
At 'submit' time, I try to validate some data on the server-side, if it fails then I display a 'toast'.
The problem is that the form is 'refreshing' the page, it seems to navigate to himself!
Because of this, I cannot display my error in the toast because of this 'kind of refresh'.
index.cshtml
#model TestModel
<form method="post">
<button type="submit">GO</button>
</form>
TestModel.cs
public virtual async Task<IActionResult> OnPostAsync()
{
_toaster.ShowError("Hellow world", "I got an issue");
return Page();
}
Any idea to solve this ?
You should remove the Blazor tag. Your issue is with Razor Pages, not Blazor.
Do you see the code in the other answer. You should do something similar to what the EditForm does in Blazor. Generally speaking, you should use the JavaScript Fetch API to communicate with the server, without submitting your form the traditional way, the result of which is full refresh of the page. I've recommended
to use the Fetch API also because Blazor employs it to communicate with API end points on the server. But you may use jQuery instead... however, I do not recommend it. I do hope that by now you've realized that you should use AJAX, right ?
Incidentally, you may create Blazor components that implement such functionality,
and include them in your Razor Pages.
I think chris sainty has built a toast library in Blazor. It may help you.
I also think I saw a push notification sample by Daniel Wroth, demonstrated when creating a PWA in Blazor.
Hope this helps...
If you moved validation client-side, you could use an EditForm and use the DataAnnotationsValidator, for example;
<EditForm Model="#CurrentObject" OnValidSubmit="#HandleValidSubmit">
<DataAnnotationsValidator />
<div class="form-group">
<label for="Name">Name</label>
<InputText id="Name" class="form-control" #bind-Value="#CurrentObject.Name" />
<ValidationMessage For="#(() => CurrentObject.Name)" />
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
</EditForm>
Where HandleValidSubmit would be your actual submission (create/update etc), #CurrentObject would be an instance of your model class, which in turn would be enriched with attributes from the System.ComponentModel.DataAnnotations namespace, eg;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace [YourNamespace].Data.Model
{
public class ExampleModel
{
// holds the front-end name for the record
[Required(ErrorMessage = "Name is required")]
public string Name { get; set; } = "";
}
}
If you wanted to keep validation serverside, you can still use EditForms, and use the "HandleSubmit" method instead as detailed here; https://learn.microsoft.com/en-us/aspnet/core/blazor/forms-validation?view=aspnetcore-3.1

How do Delete view and action get the model id?

In a standard MVC app, scaffolding controller with views gives a Delete view with this Razor form:
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
<div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-default" /> |
#Html.ActionLink("Back to List", "Index")
</div>
}
Nowhere in the Delete view is any id field, hidden or not.
Then the controller for that view has this action:
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(long id)
{
....
}
Where does this action get its id parameter value from? Is it somehow extracted from the only form value posted, the anti-forgery token __RequestVerificationToken, during some sort of model binding?
The id is passed as parameter when you redirected to the Delete action:
[HttpGet]
public ActionResult Delete(long id)
{
return View();
}
and since it is part of the original url (look at your browser address bar at the moment the Delete view is displayed) it will be preserved by the Html.BeginForm() helper - now look at the generated HTML markup and you will see this:
<form action="/somecontroller/delete/123" method="post">
...
</form>
That's where the id is coming from - the action of the generated form.
Because you have a GET method with a signature
public ActionResult Delete(long id)
and you using the default route (or at least a route definition containing /{id})
url: "{controller}/{action}/{id}"
When you navigate to that method, say using /yourController/Delete/10, the value of id is 10, and that is added to the action attribute of the <form> tag generated by your Html.BeginForm() method. When you submit the form, the value of the id parameter is bound for the route value in the forms action attribute (the DefaultModelBinder reads values from the form collection (any inputs you might have) as well as route values and query strings (among others)

How does #Html.BeginForm() work? and search result in Microsoft ASP.Net MVC 5 tutorial?

I am working on MVC 5 Asp.Net and following this tutorial. I am wondering how the heck does this fetch the result when I click the Filter button?
There comes a point where this code is added in Movie/view/Index.cshtml
#using (Html.BeginForm())
{
<p> Title: #Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
Now as far as I know, it creates a textbox and a button on screen. But how is this button calling the search(index) function and passing the value of textbox in the function, I could not get this.
It's not a stupid question. #html.BeginForm() works like this. It has some parameters you could add to it like Action Controller FormType htmlAttributes. The way it works is that if you leave it empty it will look for a post action with the same name that on the page you are now, for example if you are in on the login page, it will look for a login post action. I always write what action and controller I want it to access.
#Html.BeginForm("AddUser", "Admin", FormMethod.Post, new { #class = "my_form"}) {
}
So your post action should accept parameters that your form contains, and that can be a Model ie a Product, ViewModel or single string parameters. In your case with the search your action should look like
[HttpPost]
public ActionResult Search(string SearchString)
{
//do something here
}
Please note here, for the search string to be passed into the method. The name of the <input> has to be the same as the parameter your action takes. So our form should be like this
#using (Html.BeginForm("Search", "YOUR CONTROLLER", FormMethod.Post)){
<p> Title: #Html.TextBox("SearchString") <br />
<input type="submit" value="Filter" /></p>
}
Hope this brings clarity.

MVC - Receive Form with Viewbag Variable from database and passing to the view

i have a html form into my database.
In this form i have a value which contains a Viewbag,
for example value="#Viewbag.MyVariable"
In my view when i try to receive my form all works fine,
but my problem is that the Viewbag value are not converting
to the value which comes from my controller.
any ideia how to resolve this ?
my code:
View:
#Html.Raw(p.Form)
My form in my database looks like:
<form action="/MyController/MyAction" method="post">
<input type="hidden" name="num" value="#ViewBag.num" />
....
....
....
</form>
What i have try to do was with:
Stringbuilder a=new Stringbuilder;
#Html.Raw(a.To.String())
Your code should technically work, if you are using MVC you could try
#MvcHtmlString.Create(p.Form);
I found a solution and now i solved it.
what i have done:
in my form the only part which are different from the others
forms are the dropdownlists.
i only put the part from <select> to </select> in my
database. (only the dynamically part of my form)
in my view i have write my form and only insert the variable
which comes from my controller to insert the data from my
database on the right part in my form.
here is the code:
<form action="/MyController/MyAction" method="post">
<input type="hidden" name="num" value="#ViewBag.num" />
#MvcHtmlString.Create(p.Form);
<button type="submit" name="submit" id="submit">OK</button>
</form>
So i have never more the problem with the variables to be
converted, because the variables are still the same

More than one form in one view. Spring web flow + displaytag + checkbox

I have a table, using display tag, in my application, that is using spring web flow. I would like to have a check box in each row, a button that allows me to select/uselect all and a button to execute a function. After clicking the button, the action will perform some database actions and the page should be render, so we can see these changes.
I don´t know which could be the best option, submitting the whole table
<form method="POST" (more params)>
<display:table id="row">
....
</display:table>
</form>
Or only the checkbox column. I this case I wouldn´t know how to implement it.
I have tryed two different approaches:
1. Using a simple input text, checkbox type. This is not possible, because when I submit the form, I need to set a path to another page.jsp (I am working with flows). Besides, I wouldn´t know how to send these values to java backend.
Using spring tags.
In this case, the problem comes whith the class conversationAction
I found some examples, but allways using MVC and controller cases.
How could I implement this issue??
EDIT
I have found a kind of solution, but I faced a new problem...
flow.xml
var name="model1" class="com.project.Model1"/>
var name="model2" class="com.project.Model2"/>
view-state id="overview" model="formAggregation">
...
</view-state>
page.jsp
form:form modelAttribute="formAggregation.model1" id="overviewForm">
...
/form:form>
...
form:form method="POST" modelAttribute="formAggregation.model2">
display:table id="row" name="displayTagValueList" requestURI="overview?_eventId=tableAction">
display:column title="">
form:checkbox path="conversationIds" value="${row.threadId}"/>
/display:column>
/display:table>
input type="submit" name="_eventId_oneFunction" value="Send>>"/>
/form:form>
FormAggregation.java
#Component("formAggregation")
public class FormAggregation {
private Model1 model1;
private Model2 model2;
//Getters and setters
I need this aggregator, because I need both models. I have tested it one by one and it is working as wished. Any idea about that??
Thanks!!
I couldn´t find a solution to add two model in a view-state. So I made a workaround, adding the fields I needed to the model I was using, com.project.Model1. So the result is:
page.jsp
<form:form method="POST" id="tableForm" modelAttribute="model1">
<display:table id="row">
<display:column title="">
<form:checkbox path="chosenIds" value="${row.id}"/>
</display:column>
<display:footer>
<div class="tableFooter" >
<input type="submit" name="_eventId_workIds" value="Send"/>
</div>
</display:footer>
</display:table>
</form:form>
flow.xml
<var name="model1" class="com.project.Model1"/>
...
<transition on="workIds" to="overview" validate="false">
<evaluate expression="actionBean.workIds(model1.chosenIds)" />
</transition>
java class
public void workIds(List<Long> ids) {
Hope it helps

Resources