I need to implement multiple Ajax forms.
html
#using (Ajax.BeginForm("PerformAction", "Home", new AjaxOptions { OnSuccess = "OnSuccess", OnFailure = "OnFailure" }))
{
<h3>This is a demo form #1.</h3>
#Html.LabelFor(model => model.FirstName)
#Html.TextBoxFor(model => model.FirstName, null, new { #class = "labelItem" })
<input type="submit" value="Submit" />
}
<br />
<br />
#using (Ajax.BeginForm("PerformAction2", "Home", new AjaxOptions { OnSuccess = "OnSuccess2", OnFailure = "OnFailure2" }))
{
<h3>This is a demo form #2. </h3>
#Html.LabelFor(model => model.FirstName)
#Html.TextBoxFor(model => model.FirstName, null, new { #class = "labelItem" })
<input type="submit" value="Submit" />
}
<br />
<br />
<script type="text/javascript">
function OnSuccess(response) {
alert(response);
}
function OnFailure2(response) {
alert("222 Whoops! That didn't go so well did it?");
}
function OnSuccess2(response) {
alert(response);
}
function OnFailure(response) {
alert("Whoops! That didn't go so well did it?");
}
</script>
C#
[AcceptVerbs("POST")]
public ActionResult PerformAction(FormCollection formCollection, Person model)
{
model.FirstName += " Form 1";
return View(model);
}
[AcceptVerbs("POST")]
public ActionResult PerformAction2(FormCollection formCollection, Person model)
{
model.FirstName += " Form 2";
return View(model);
}
But I am facing the error about that ASP .NET MVC 4 is looking for some kind of partial form.
I don't want to use any partial form and just I need to get working JavaScript OnSuccess and OnSuccess2
Any guess how it could be done?
Using View() or PartialView(), MVC it will try to find a view with a name equals to the action name.
So, just don't return a View(model)
Return a EmptyResult() or a JSON object.
Related
I have an old MVC website I'm looking at. I don't understand the following code in my Account controller. (I believe this was code generated by ASP.NET.)
Controller
//
// GET: /Account/ResetPassword
[AllowAnonymous]
public ActionResult ResetPassword(string code)
{
return code == null ? View("Error") : View();
}
//
// POST: /Account/ResetPassword
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await UserManager.FindByNameAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
if (result.Succeeded)
{
return RedirectToAction("ResetPasswordConfirmation", "Account");
}
AddErrors(result);
return View();
}
View
#model OnBoard101.Models.ResetPasswordViewModel
#{
ViewBag.Title = "Reset password";
}
<h2>#ViewBag.Title</h2>
#using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { #class = "form-horizontal", role = "form" }))
{
#Html.AntiForgeryToken()
<h4>Reset your password</h4>
<hr />
#Html.ValidationSummary("", new { #class = "text-danger" })
#Html.HiddenFor(model => model.Code)
<div class="form-group">
#Html.LabelFor(m => m.Email, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.TextBoxFor(m => m.Email, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.Password, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.Password, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
#Html.LabelFor(m => m.ConfirmPassword, new { #class = "col-md-2 control-label" })
<div class="col-md-10">
#Html.PasswordFor(m => m.ConfirmPassword, new { #class = "form-control" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" class="btn btn-success" value="Reset" />
</div>
</div>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
These methods are called when the user uses the Forgot Password feature and then clicks the link that is sent to them in an email.
As best I can tell, the POST handler correctly detects an invalid code in the link (it produces an Invalid Token error when the code is not value). But I don't understand how. The GET handler seems to simply discard the code argument.
I don't get how this code works. How does model.Code ever get populated?
The ResetPassword feature does use code from the link.
Model binding retrieves data from various sources such as route data, form fields, and query strings.
It inspects the query string parameters for matching properties on the model used by the view
While it may appear like the code is being discarded by the Controller GET action, the code is still a part of the request and used by the view.
And since the view explicitly binds to a model
#model OnBoard101.Models.ResetPasswordViewModel
which has a matching public Code property (case-insensitive)
public string Code { get; set; }
it will bind it to the model in the view during the GET and then use it (the model) to populate a hidden form field (as shown in your View markup)
#Html.HiddenFor(model => model.Code)
So now when the form is submitted, the POST action will bind that field to the model posted back to the action and perform the validation
The same could have been achieved with
// GET: /Account/ResetPassword
[AllowAnonymous]
public ActionResult ResetPassword(string code) {
if (code == null) return View("Error");
var model = new ResetPasswordViewModel {
Code = code
};
return View(model);
}
But since the built-in model binding functionality would initialize a model if one was not provided, the above code really does not add anything additional to what the framework does out-of-the-box.
Good day
I am working with 7 partial views on my index page.
Index.cshtml (code section that creates the partial views in their own tabs)
#model project1.Models.MasterModel
<div class="tab-content col-lg-9 col-md-9 col-sm-9 col-xs-9" style="margin-bottom:110px;">
<div id="partial1" class="tab-pane fade in active">
#Html.Partial("partial1", Model)
</div>
<div id="partial2" class="tab-pane fade in">
#Html.Partial("partial2", Model)
</div>
<div id="partial3" class="tab-pane fade in">
#Html.Partial("partial3", Model)
</div>
<div id="partial4" class="tab-pane fade in">
#Html.Partial("partial4", Model.Owners)
</div>
<div id="partial5" class="tab-pane fade in">
#Html.Partial("partial5", Model)
</div>
<div id="partial6" class="tab-pane fade in">
#Html.Partial("partial6", Model)
</div>
<div id="partial7" class="tab-pane fade in">
#Html.Partial("partial7", Model)
</div>
On partial1 I have a submit button that should populate the other partial views with the information that is submitted on the first partial view.
My Model consist of 7 models (one for each partial view)
MasterModel.cs
public class MasterModel
{
public DisplayPartial1 view1 {get;set;}
public DisplayPartial2 view2 {get;set;}
public DisplayPartial3 view3 {get;set;}
public DisplayPartial4 view4 {get;set;}
public DisplayPartial5 view5 {get;set;}
public DisplayPartial6 view6 {get;set;}
public DisplayPartial7 view7 {get;set;}
}
In my controller's Index Action result I create a new instance of the MasterModel and then I create new instances for all the sub models and return to the Index view.
MainController.cs
// Global variable used and returned by all partial views
MasterModel main = new MasterModel();
public ActionResult Index()
{
MasterModel master = new MasterModel();
master.view1 = new DisplayPartial1 ();
master.view2 = new DisplayPartial2 ();
master.view3 = new DisplayPartial3 ();
master.view4 = new DisplayPartial4 ();
master.view5 = new DisplayPartial5 ();
master.view6 = new DisplayPartial6 ();
master.view7 = new DisplayPartial7 ();
return View(master);
}
public ActionResult MyPartial1()
{
return PartialView("MyPartial1", master);
}
[HttpPost]
public ActionResult MyPartial1(MasterModel model, string submitButton)
{
if(submitButton == "GetInfo")
{
/*Process input values*/
//wcf service return data
main.view1.id = serviceObject.Id;
...
main.view4.name = serviceObject.Name;
...
}
return PartialView("MyPartial1", master);
}
When MyPartial1 is returned then the other 6 partial view do not update with the assigned information until I do a submit call with a java script that looks like the following:
<script type="text/javascript">
$(document).ready(function () {
$('#input1').change(function () {
$('form').submit();
});
$('#input2').change(function () {
$('form').submit();
});
});
</script>
An Example Partial view (all the partial views work on the same principals)
#model OperatorLicense.Models.MasterModel
#using (Ajax.BeginForm("MyPartial1", "Operator", null, new AjaxOptions
{
UpdateTargetId = "MyPartial1",
InsertionMode = InsertionMode.Replace,
HttpMethod = "Post"
}, new { id = "MyPartial1" }))
{
#Html.TextBoxFor(model => model.view1.SerialNumber, new { id="SerialNumber", #class = "form-control", placeholder = Html.DisplayNameFor(n => n.view1.SerialNumber) })
...
}
Is there a way to refresh the other partial views when the MyPartial1 partial view has returned so that the assaigned values can be displayed on the required partial view?
You can use OnSuccess or OnComplete property of AjaxOptions class.
#using (Ajax.BeginForm("MyPartial1", "Operator", null, new AjaxOptions
{
UpdateTargetId = "MyPartial1",
InsertionMode = InsertionMode.Replace,
HttpMethod = "Post",
OnSuccess="partial1Success"
}, new { id = "MyPartial1" }))
{
#Html.TextBoxFor(model => model.view1.SerialNumber, new { id="SerialNumber", #class = "form-control", placeholder = Html.DisplayNameFor(n => n.view1.SerialNumber) })
...
}
define partial1Success method in javascript
<script type="text/javascript">
function partial1Success(){
// write your other partial view refresh logic here
}
</script>
partial1Success method called after from submit successfully.
I'm using partial pages within modal dialogues to handle various CRUD actions elsewhere on a website and it's working fine, I have done everything the same with the login (shown below), but the HttpPost actionresult in the controller is not getting hit and I'm not sure why.
Instead the HttpGet is being called.
What have I missed?
Login partial
#model Models.User
<script language="Javascript" type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script language="Javascript" type="text/javascript" src="http://code.jquery.com/ui/1.10.3/jquery-ui.js"></script>
<script type="text/javascript">
$(function () {
$('#btn-login').click(function () {
$('#modal-container').modal('hide');
});
$('#btn-close').click(function () {
$('#modal-container').modal('hide');
});
});
</script>
<div class="login-container">
#using (Html.BeginForm())
{
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="login-table">
<div>
#Html.LabelFor(m => m.Username)
#Html.TextBoxFor(m => m.Username)
#Html.ValidationMessageFor(m => m.Username, "", new { #class = "text-danger" })
</div>
<div>
#Html.LabelFor(m => m.Password)
#Html.PasswordFor(m => m.Password)
#Html.ValidationMessageFor(m => m.Password, "", new { #class = "text-danger" })
</div>
</div>
<div>
<button type="submit" id="btn-login" class="btn btn-sm">Login</button>
<button type="button" class="btn btn-default modal-close-btn" data-dissmiss="modal">Cancel</button>
</div>
}
</div>
Account Controller Login Action Methods
[AllowAnonymous]
[HttpGet]
public ActionResult Login()
{
return PartialView("Login");
}
[HttpPost]
public ActionResult Login(User model)
{
if(ModelState.IsValid)
{
// do stuff
}
return RedirectToAction("Index", "Announcements");
}
Your GET method is marked with [AllowAnonymous] suggesting your controller is marked with [Authorize], which means that you POST method must also be marked with [AllowAnonymous] (the user is authorized until the code in this method is executed)
[HttpPost]
[AllowAnonymous]
public ActionResult Login(User model)
{
if(ModelState.IsValid)
{
// do stuff
}
return RedirectToAction("Index", "Announcements");
}
Try this in form attribute
#Html.BeginForm("Login", "Home", , new { modal= Model }, FormMethod.Post)
//Login- action Name that has to be hit
//Home - Controller name
So here, I need to add comment for video in one view.
I have the main view code like this that displaying video and comment for that video.
<!-- language: C# -->
#model AzureMediaPortal.ViewModels.ViewModelWatch
#{
ViewBag.Title = "Watch";
}
<div id="videoPlayer">
</div>
<h2>#Html.DisplayFor(model => model.media.Title)</h2>
<h3> By #Html.DisplayFor(model => model.media.UserId) at #Html.DisplayFor(model => model.media.UploadDate) </h3>
#Html.HiddenFor(model => model.media.Id)
#Html.HiddenFor(model => model.media.AssetId)
#Html.HiddenFor(model => model.media.FileUrl, new { id = "fileUrl" })
<div class="display-label" style="font-weight:bold">
#Html.DisplayNameFor(model => model.media.Description)
</div>
<div class="display-field">
#Html.DisplayFor(model => model.media.Description)
</div>
<br />
<div class="display-label" style="font-weight:bold">
#Html.DisplayName("Category")
</div>
<div class="display-field">
#Html.DisplayFor(model => model.media.Category.CategoryName)
</div>
<h3>Comments</h3>
#foreach (var item in Model.comment)
{
<div class="display-label" style="font-weight:bold">
#item.UserId
</div>
<div class="display-field">
#item.Content
</div>
}
#Html.Partial("Post",new AzureMediaPortal.ViewModels.ViewModelWatch())
#section Scripts {
<script src="~/Scripts/playerframework.min.js"></script>
<script src="~/Scripts/media-player.js"></script>
#Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
mediaPlayer.initFunction("videoPlayer", $("#fileUrl").val());
</script>
}
and this the partial view
#model AzureMediaPortal.ViewModels.ViewModelWatch
#{
ViewBag.Title = "Post";
}
<h2>Add Comment</h2>
#Html.HiddenFor(model => model.cmnt.MediaElement.Id)
#using (Html.BeginForm("Post","Home",FormMethod.Post)) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Add Comment</legend>
<div class="editor-label" style="font-weight:bold">
#Context.User.Identity.Name
</div>
<div class="editor-field">
#Html.TextAreaFor(model => model.cmnt.Content)
#Html.ValidationMessageFor(model => model.cmnt.Content)
</div>
<p>
<input type="submit" value="Post" />
</p>
</fieldset>
}
#section Scripts {
#Scripts.Render("~/bundles/jqueryval")
}
this is my ViewModel
public class ViewModelWatch
{
public MediaElement media { get; set; }
public List<Comment> comment { get; set; }
public Comment cmnt { get; set; }
}
and this is my controller
public ActionResult Watch(int id)
{
ViewModelWatch vm = new ViewModelWatch();
vm.media = _repository.GetMedia(id);
vm.comment = _repository.GetMediaComment(id);
return View(vm);
}
public ActionResult Post()
{
return View();
}
[HttpPost]
public ActionResult Post(Comment comment, int id)
{
if (ModelState.IsValid)
{
comment.UserId = User.Identity.Name;
comment.MediaElement.Id = id;
db.Comments.Add(comment);
db.SaveChanges();
return RedirectToAction("Watch");
}
return View();
}
I need to pass data from partial view and save it to database include the media.Id to know that comment inserted for the video.
Thanks so muchhh
putting scripts on a partial view is generally bad practice. Script gets inserted into the middle of the view. For saving information from a partial view I use ajax calls. To do that add a class to your post button
<input type="button" class="btnSubmit" value="Post" />
then in your script on the main page
$(document).on('click', '.btnSubmit', function(){
$.ajax({
url: '#Url.Action("Action", "Controller")',
cache: false,
async: true,
data: {
//put the data that you want to save from the partial here
id: $('#hiddenID').val(),
content: $('#Content').val()
},
success: function (_result) {
//can add something here like an alert, close a popup something along those lines
}
});
});
just make sure the inputs on your controller match exactly the names that you have defined here
[HttpPost]
public ActionResult Action(int id, string content){
//database call to save the fields
//see here for an example of returning json http://stackoverflow.com/questions/1482034/extjs-how-to-return-json-success-w-data-using-asp-net-mvc
return Json(json);
}
I would suggest using #Html.Action and get the create form from there. Also, once the comments are stored you can redirect to the parent action. That should automatically update the comments list.
But that would be a bad idea.
Rather you can put get your comments by calling action from ajax ($.ajax) and use pure.js to replace the older ones with the new comment list.
I am beginner and I think my question is very obvious but I am stuck in it!
In MVC and trying to pass a custom Model (class) which is not my view's main Model to my controller.
My Razor code is as follow:
#helper CreatForm()
{
MyViewModel myModel = new MyViewModel();
using (Html.BeginUmbracoForm("Post", "ShowPost", FormMethod.Post, new { #class = "formCM" }))
{
myModel.PostNode = Node.GetCurrent();
<div class="row">
#Html.TextBoxFor(x => myModel.Name, new Dictionary<string, object> { { "placeholder", "Name" } })
</div>
<div class="row">
#Html.TextBoxFor(x => myModel.Email, new Dictionary<string, object> { { "placeholder", "Email Address" } })
</div>
<div class="row">
#Html.TextBoxFor(x => myModel.Website, new Dictionary<string, object> { { "placeholder", "Website" } })
</div>
<div class="row tall">
#Html.TextAreaFor(x => myModel.Comment, new Dictionary<string, object> { { "placeholder", "Comment" } })
</div>
<div class="row">
<input type="submit" id="Submit" name="Submit" value="Submit" />
</div>
}
}
Clicking on Submit button will take me to the controller but the Model is always empty.
My controller is like below:
[HttpPost]
public ActionResult Post(MyViewModel model)
{
return this.View();
}
Any suggestions? Do I have to add this MyModel properties to current page's ViewData?
Create a partial-view that takes MyViewModel -- that will be required to make Html.TextBoxFor() work the way you want it to. Then call that partial view from your main view. Let's say you name the view "myForm", and place it in the shared folder. Then in your main view:
#Html.Partial("myForm", myModel)