Passing view model from razor view to controller action - c#

I have a problem, when using asp.net core 2.2.
I have a model named "Test".
public class Test
{
public string Email { get; set; }
}
And a controller named "UserController"with these actions:
public IActionResult Test()
{
var test = new Test
{
Email = "Hamid#gmail.com"
};
return View(test);
}
[HttpPost]
public IActionResult Test(Test param)
{
if (ModelState.IsValid)
{
}
return View();
}
and view with named "test.cshtml" is:
#model Test
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Test</title>
</head>
<body>
<form asp-controller="User" asp-action="Test" asp-area="Account" method="post">
<div class="form-group row">
<div class="col-lg-3 col-12">
<label asp-for="Email" class="col-form-label">Email:</label>
</div>
<div class="col-lg-9 col-12">
<input asp-for="Email" class="form-control email"
value="#Model.Email" autofocus="autofocus" />
</div>
</div>
<input type="submit" value="Send" />
</form>
</body>
</html>
When i sending model to the view, no problem,
But when I click on submit button for sending form to the action,then my model is null.

My problem solved.
With remove this line:
#removeTagHelper Microsoft.AspNetCore.Mvc.TagHelpers.InputTagHelper, Microsoft.AspNetCore.Mvc.TagHelpers

Related

Show validation messages on partial views in asp.net core MVC

I have the following model in order to show validations on multiselect list
using Microsoft.AspNetCore.Mvc.Rendering;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Threading.Tasks;
namespace AccountManagementUI.Models
{
public class NewMembersAddViewModel
{
public string GroupId { get; set; }
public string GroupName { get; set; }
public List<SelectListItem> membersList { get; set; }
[Required(ErrorMessage ="Please select atlast 1 employee")]
public List<Guid> selectedMembersId { get; set; }
}
}
My Controller post method is as follows:
[HttpPost]
public IActionResult GetNewMembers(NewMembersAddViewModel groupMemberData)
{
if (ModelState.IsValid)
{
AddMembersToGroup addMembersToGroup = new AddMembersToGroup();
addMembersToGroup.GroupId = groupMemberData.GroupId;
foreach (var memberId in groupMemberData.selectedMembersId)
{
addMembersToGroup.UserIds.Add(memberId.ToString());
}
_gateway.AddMembersToGroup(addMembersToGroup);
return RedirectToAction("GroupMembers", "Group", new { groupId = groupMemberData.GroupId });
}
else
{
return PartialView("_GetNewMembers", groupMemberData);
}
}
My view is as below:
#model AccountManagementUI.Models.NewMembersAddViewModel
<!DOCTYPE html>
<html lang='en'>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Active Directory Management Portal</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="" />
<meta name="keywords" content="" />
<!-- Latest compiled and minified CSS -->
<!-- Pagelevel Initializations Of Plugins -->
</head>
<body>
<form class="console-panel grid-stack-item-content" asp-action="GetNewMembers" asp-controller="Group" method="post">
<input type="hidden" asp-for="GroupId" />
<input type="hidden" asp-for="GroupName" />
<div class="console-panel-body pl-0 pr-0">
<div class="console-form-body ">
<div class="row">
<div class="col-lg-12 col-md-12">
<div class="form-group row">
<label class="col-2 col-form-label">Members</label>
<div class="col-10">
<select asp-for="selectedMembersId" asp-items="Model.membersList" multiple="multiple" placeholder="Select Members" onchange="console.log($(this).children(':selected').length)" class="search-box form-control">
</select>
<span asp-validation-for="selectedMembersId" class="text-danger"></span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="console-footer">
<button class="btn btn-sm btn-info" type="submit">Submit</button>
<a id="addMembersCancel" class="btn btn-sm btn-secondary" onclick="AddNewMembersCancel()">Cancel</a>
</div>
</form>
<script>
$('.search-box').SumoSelect({ csvDispCount: 3, search: true, searchText: 'Enter here.' });
</script>
<script>
function AddNewMembersCancel() {
$('#addNewMemberModal').modal('hide');
}
</script>
</body>
</html>
I have given validations of selecting at least one member but when I click submit button without selecting member then it redirects to new page and shows the message there. I want to show the message on the same partial view when clicked submit?
You need to add your validation scripts jquery.validate.min.js and jquery.validate.unobtrusive.min.js.
Client-side validation
The partial view _ValidationScriptsPartial.cshtml from shared folder can be added to your view:
<partial name="_ValidationScriptsPartial" />
You have <form> element with a submit button which by default will cause you page to reload on submit.
In order to show the error on the same page when you click submit, you need to prevent the default behavior of the form.
First, you will need some kind of id on your form element. Let's say the id is new-members-form.
<form id="new-members-form" class="console-panel grid-stack-item-content" asp-action="GetNewMembers" asp-controller="Group" method="post">
...
</form>
Then, you need to select the form and tell it to stop executing the default behavior on form submit.
With JQuery:
$("new-members-form").on("submit", (event) => { event.preventDefault(); });
Or plain JS:
document.getElementById("new-members-form").addEventListener("submit", function(event) {
event.preventDefault();
});
When first time to view or failed to add, remember to set the memberList.
Codes of controller:
//Members to SelectListItem
public IList<SelectListItem> GetMembers()
{
var members = new List<Member>
{
new Member {Id = Guid.NewGuid(), Name = "Ada"},
new Member {Id = Guid.NewGuid(), Name = "Brain"},
new Member {Id = Guid.NewGuid(), Name = "Cater"},
};
var memberListItem = members
.Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() })
.ToList();
return memberListItem;
}
[Route("/members")]
public IActionResult _GetNewMembers()
{
var model = new NewMembersAddViewModel {
membersList = GetMembers()
};
return View(model);
}
[Route("/api/Group/GetNewMembers")]
[HttpPost]
public IActionResult GetNewMembers(NewMembersAddViewModel groupMemberData)
{
if (ModelState.IsValid)
{
//Success
return RedirectToAction("GroupMembers", "Group", new { groupId = groupMemberData.GroupId });
}
else
{
//when failed, set the memberList again.
groupMemberData.membersList = GetMembers();
return PartialView("_GetNewMembers", groupMemberData);
}
}
Codes of view are same as you.

Using IsPost in asp.net core razor page to display text after form submission

I'm trying to use the IsPost method in my asp.net core web page, but it says it does not exist in the current context. Since I'm not using MVC, (other than the fact that I have a models folder), is it possible for me to use IsPost in my razor page? Basically I am trying to display confirmation text on the same page after the user hits the submit button, so if anyone has a better way of doing this, please suggest so. Thanks
FreeConsultation.cshtml
#page
#model GuptaAccounting.Pages.FreeConsultationModel
#{
ViewData["Title"] = "FreeConsultation";
}
<head>
<script src="~/js/site.js"></script>
</head>
<div class="container" style="padding:30px;">
<br />
<h1 class="text-info">Get a FREE Consultation</h1>
<br />
#if (IsPost)
{
<p>Consultation requested. I will get back to you as soon as possible</p>
}
else
{
<form method="post">
<div class="text-danger" asp-validation-summary="ModelOnly"></div>
<!-- More of the form here -->
<div class="form-group row">
<div class="col-3 offset-3">
<input type="submit" value="Submit" onclick="return Validate()" class="btn btn-primary form-control" />
</div>
</div>
</form>
}
FreeConsultation.cshtml.cs
public class FreeConsultationModel : PageModel
{
private readonly ApplicationDbContext _db;
public FreeConsultationModel(ApplicationDbContext db)
{
_db = db;
}
[BindProperty]
public Client Client { get; set; }
public void OnGet()
{
}
public async Task<IActionResult> OnPost()
{
if (ModelState.IsValid)
{
Client.IsConsultationClient = true;
await _db.Client.AddAsync(Client);
await _db.SaveChangesAsync();
return RedirectToPage("Index");
}
else
{
return Page();
}
}
}
I don't think razor pages have an IsPost method but you could add an IsPost property to your FreeConsultationModel and set it to true in the OnPost() method.

File upload in C# with ASP.NET MVC without razor

I am trying to submit a form containing a file upload using c# ASP MVC with Entity. My problem is that the file is always null.
The view :
#model Com.Work.With.Me.Models.ObjVM
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
</head>
<body>
<form id="formObj" action="AddMe">
<input type="file" id="objPdfFile" name="Obj.PdfFile" />
</select>
<input type="text" id="objName" name="Obj.Name" />
</form>
The viewmodel :
public class ObjVM
{
public string Name{ get; set; }
public HttpPostedFileBase PdfFile{ get; set; }
public ObjVM()
{
}
}
The controller :
public ActionResult AddMe(ObjVM obj)
{
//her obj.Name is fine
//but obj.PdfFile is null
return View();
}
Any ideas?
Thanks to #DiskJunky, I corrected my form adding method="post" enctype="multipart/form-data":
<form id="formObj" action="AddMe" method="post" enctype="multipart/form-data">
<input type="file" id="objPdfFile" name="Obj.PdfFile" />
</select>
<input type="text" id="objName" name="Obj.Name" />
</form>
And my controller adding [HttpPost] :
[HttpPost]
public ActionResult AddMe(ObjVM obj)
{
//obj.PdfFile is not null anymore !
return View();
}
Add Your Ui to this Code `enctype = "multipart/form-data"` Code
#using (Html.BeginForm("Action Name", "Control Name", null, FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<input type="file" id="objPdfFile" value="#Model.PdfFile" name="Obj.PdfFile" />
</select>
<input type="text" id="objName" value="#Model.Name" name="Obj.Name" />
}

Post form from modal partial view to a different controller with a routeprefix attribute

I have a partial view that has a form - I launch this partial from the Home controller.
#using (Html.BeginForm("CloudContent","Files", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
#Html.HiddenFor(m => m.MyProperty);
#Html.HiddenFor(m => m.SelectedIds);
}
I want to post this form to the Files controller, however the files controller has a route prefix:
[RoutePrefix("sth/api/v1/files")]
Which results in my form action being empty.
It doesn't seem to be added to named routes, so I cannot use the beginrouteform. Also, I have little influence over the application, so it's best handled in my form or partial view...
The method that I want to post to in the files controller:
[HttpPost]
[Route("getcloudcontent")]
public List<ConnectedFile> CloudContent(CloudFilesModel model)
{
//do magic
}
UPDATE:
Here is another example which includes partial view / child action:
HomeController.cs:
using System.Web.Mvc;
public class HomeController : Controller
{
[Route("~/")]
public ActionResult Index()
{
return View();
}
[Route("ModalContent")]
[ChildActionOnly]
public ActionResult ModalContent()
{
return View();
}
}
FilesController.cs:
using System.Web.Mvc;
[RoutePrefix("sth/api/v1/files")]
public class FilesController : Controller
{
[HttpPost]
[Route("getcloudcontent")]
public ActionResult CloudContent(string model)
{
return Content("test");
}
}
Views\Home\Index.cshtml:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Show modal
</button>
<div class="modal fade" id="myModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
#Html.Action("ModalContent")
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
Views\Home\ModalContent.cshtml:
#using (Html.BeginForm("CloudContent", "Files", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
}
Global.asax.cs:
using System.Web.Mvc;
using System.Web.Routing;
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
RouteTable.Routes.MapMvcAttributeRoutes();
}
}
And the result HTML:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<button type="button" class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
Show modal
</button>
<div class="modal fade" id="myModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<form action="/sth/api/v1/files/getcloudcontent" enctype="multipart/form-data" method="post">
<div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
</form>
</div>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
There is something different that is wrong with your code. I ran your code and it worked without any issues.
Here is the code:
FilesController.cs:
using System.Web.Mvc;
namespace Controllers
{
[RoutePrefix("sth/api/v1/files")]
public class FilesController : Controller
{
[Route("")]
public ActionResult Index()
{
return View();
}
[HttpPost]
[Route("getcloudcontent")]
public ActionResult CloudContent(string model)
{
return Content("test");
}
}
}
Index.cshtml:
#using (Html.BeginForm("CloudContent", "Files", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
}
Global.asax.cs:
using System.Web.Mvc;
using System.Web.Routing;
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
RouteTable.Routes.MapMvcAttributeRoutes();
}
}
When I go to http://localhost/sth/api/v1/files I see the following HTML:
<!DOCTYPE html>
<html>
<head><title>Test</title></head>
<body>
<form action="/sth/api/v1/files/getcloudcontent" enctype="multipart/form-data" method="post"> <div id="container"></div>
<input type="submit" name="PostMe" title="Submit" value="Submit Form" />
</form>
</body>
</html>
Notice that form action has the correct URL which includes prefix.

Submit form using MVC 4 don't trigger my Action specified at my BeginForm

I have a problem to submit my form to a specific method in my Controller.
When the user click on my submit button, the Index action is triggered, ignoring my ValidateLogin action that was specified at my BeginForm
What's the problem with my Form ?
HTML
#model Login.Models.Autenticacao
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="~/Content/bootstrap.css" rel="stylesheet" />
<link href="~/Content/endless.css" rel="stylesheet" />
<script src="~/Scripts/jquery-1.8.2.js"></script>
</head>
<body>
<div id="formAutenticacao">
<div class="pace pace-inactive">
<div data-progress="99" data-progress-text="100%" style="width: 100%;" class="pace-progress">
<div class="pace-progress-inner"></div>
</div>
<div class="pace-activity"></div>
</div>
<div class="login-wrapper">
<div class="text-center">
<h2 class="fadeInUp animation-delay8" style="font-weight: bold">
<img src="~/Images/Horizonta_com_S.png" />
</h2>
</div>
<div class="login-widget animation-delay1">
<div class="panel panel-default">
<div class="panel-body">
#using (Html.BeginForm("ValidateLogin", "Login", FormMethod.Post))
{
<div class="form-group">
<label>User</label>
#Html.TextBoxFor(m => m.UserName, new {placeholder = "Type user name", Class = "form-control input-sm bounceIn animation-delay2"})
</div>
<div class="form-group">
<label>Password</label>
#Html.PasswordFor(m => m.Password, new {placeholder = "Type the password", Class = "form-control input-sm bounceIn animation-delay4"})
</div>
<div class="seperator"></div>
<hr>
<input type="submit" value="Go!" />
}
</div>
</div>
</div>
</div>
</div>
<iframe id="iframePrincipal" height="0" width="100%" frameborder="0"></iframe>
</body>
</html>
Login Controller
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult ValidateLogin(Autenticacao form)
{
return View();
}
Route
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Login", action = "Index", id = UrlParameter.Optional }
);
}
Model
public class Autenticacao
{
[Required]
public virtual string UserName { get; set; }
[Required]
public virtual string Password { get; set; }
}
Firebug
FYI: I translated the name of my Action to a better understand in this question.
Found my error.
In Web.config I comment the following line
<authorization>
<deny users="?" />
</authorization>

Categories

Resources