I have 2 anchor links in my view, on which I am trying to hit the HTTP POST method on the controller. The POST method has a condition in which it checks value of a hidden field, and on the basis of the condition, it tries to redirect to different views.
Facing a problem that the value of the hidden field is being NULL everytime, irrespective of the fact that I am setting the value of the hidden field via jQuery.
Below is the code:
<form id="CreateForm" asp-action="CreateForm" method="post" role="form">
<a style="cursor:pointer" onclick="Submit();" id="finishCreateForm">Finish</a>
#Html.Partial("~/_Partial1.cshtml", Model.Contact)
</form>
#section Scripts {
<script>
function Submit() {
$("#CreateForm").submit();
$("#myHiddenField").val = "SubmitCreateForm";
}
</script>
}
<input type="hidden" name="nameHiddenField" id="myHiddenField"/>
In the partial _Partial.cshtml, we have another anchor link, as below:
#model Contact
<span>
<input asp-for="AddressLine1" value="#Model.AddressLine1" />
<span asp-validation-for="AddressLine1"></span>
<a id="find" value="findSubmit" onclick="Find();" style="cursor:pointer">Find</a>
</span>
<script>
function Find() {
$("#CreateForm").submit();
}
</script>
The controller code:
[Route("CreateForm")]
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> CreateForm(InputViewModel inputVM)
{
if (ModelState.IsValid)
{
//Some business logic stuffs, code removed for brevity
if (inputVM.myHiddenField== "SubmitCreateForm")
{
return RedirectToAction("Test", "Home", new { area = "Shared" });
}
else
{
return RedirectToAction("Search", "MySearch", new { id= response.Id, type= response.Type, area = "Search" });
}
}
else
{
//Some more logic
}
}
I have also added myHiddenField in the model coming to the POST action method, as
public string myHiddenField{ get; set; }
I know I am missing a very basic stuff, please guide accordingly.
Thanks
Related
I use an Ajax call to update my model value and then have that new value should be shown in the view. Here is my code . In this code I am calling a method GetText and updating model value. How can I show the new model value in the html. Please help
public class EmpModel
{
public string EmpClaim {get;set;}
}
public IActionResult EmpClaim()
{
return View();
}
[HttpPost]
public ActionResult GetText(EmpModel model)
{
model.EmpClaim = "New Text" // This should be shown in view
return Json(data);
}
Html file
#model Test.Models.EmpModel
<div>
<input type="text" name="Claim" class="form-control" id="TxtClaim" asp-for="Claim" data-role="text"/>
</div>
<div>
<input type="button" onclick="changeText()" id="changeButton" />
</div>
Javascript
<script>
function changeText()
{
var url = '#Url.Action("GetText", "EmpDoc")';
$.post(url, $('form').serialize(), function (view) {
$("#TxtClaim").val(); // How can I update the TxtClim with model.EmpClaim "New Text"
});
}
</script>
You can use return Content() to return string to ajax function.
[HttpPost]
public IActionResult GetText(EmpModel model)
{
model.EmpClaim = "New Text" // This should be shown in view
return Content(model.EmpClaim);
}
Js:
<script>
function changeText()
{
var url = '#Url.Action("GetText", "EmpDoc")';
$.post(url, $('form').serialize(), function (view) {
$("#TxtClaim").val(view); // How can I update the TxtClim with model.EmpClaim "New Text"
});
}
</script>
Here is the result:
Note:
In your case, the model does not have a key field, so when you update the data, you cannot determine which piece of data to update. Further operations may require you to modify the model design.
You can refer to this.
In my MVC application I have a View containing
1. One drop down list
2. One File Upload
3. One button for submitting the form.
form code (View)
<form id="upload" enctype="multipart/form-data" action="#Url.Action("ExcelUpload", "NBL")" method="POST">
#Html.DropDownList("CustomerName", new List<SelectListItem>
{
new SelectListItem() {Text = "Customer 1", Value="CM1"},
new SelectListItem() {Text = "Customer 2", Value="CM2"}
}, new { #class = "form-control", #style = "width:auto" })
<input type="file" name="fileUpload" id="fileUpload" size="23" style="margin-top:5px"/>
<button class="btn btn-primary">Upload</button>
</form>
I am able to pass my File in Controller successfully when I click the button.
Controller code
public ActionResult ExcelUpload(HttpPostedFileBase FileUpload)
{
if (FileUpload != null)
{
// Do Stuff here.
}
}
My Problem is I also want the drop down selected value in the controller when I click the button. How can I pass both the Drop down Selected value and the file together in the controller?
The name of the dropdown element is CustomerName and it's within the form. The browser will post it to the server as a key-value pair with the key being the name of the dropdown and the value will be the value the user has selected.
The MVC framework's default binder will look for an action named ExcelUpload that either has a parameter string customerName or the action has a complex type (Model) that has CustomerName as the property.
Change your action to:
ExcelUpload(HttpPostedFileBase FileUpload, string customerName)
The problem is your model as it is does not represent the view or data you want to use. So make a model like so:
using System.ComponentModel.DataAnnotations;
namespace Models
{
public class MyUploadModel
{
[Required]
public HttpPostedFileBase File { get; set; }
[Required]
public string CustomerName { get; set; }
}
}
Use that model in your views to generate the form and then in controller:
public ActionResult ExcelUpload(Models.MyUploadModel myModel)
{
if (ModelState.IsValid)
{
// all good, save
}
return View(myModel);
}
Of course you could just add a string-parameter to your action, but this is much more robust and represents the MVC-pattern (Model/View/Controller).
I was wondering if anyone could explain how to manipulate content for various sections of a page depending on if a button is clicked. I think what I am looking for is similar to an include in php. I wasnt sure if asp.net had a way to do the same (partial view?) or if bootstrap/jquery is the way to go. I've included a .png to illustrate what I am trying to do.
I would like section b's content to change based on what button is selected in section A. While not necessarily relevant to this question.. I then would like various user inputs in section B to manipulate existing content in section C.
In your controller, have an action that returns a PartialView:
public PartialViewResult MyPartial(string someText)
{
var model = new MyPartialModel {SomeStuff = someText};
return PartialView(model);
}
Create the model and partial view as you would any other:
public class MyPartialModel
{
public string SomeStuff { get; set; }
}
Partial View:
#model ExampleApp.Models.MyPartialModel
#Html.TextBoxFor(m => m.SomeStuff)
Then on your page you can load in your partial via ajax with jQuery:
<div>
<button type="button" id="load-partial">Load The Partial!</button>
</div>
<div id="section-b"></div>
#section Scripts{
<script>
$(document).ready(function () {
$('#load-partial').click(function () {
$.get('MyPartial', { sometext: "Hello!" }).done(function (data) {
$('#section-b').html(data);
});
});
});
</script>
}
Edit to answer comment:
If you don't want to instantiate a new model in the controller each time, you can pass the model (more or less) directly from the view.
In you controller, have a very simple action that accepts a model as a parameter and returns the partial view. Note the HttpPost attribute.
[HttpPost]
public PartialViewResult MyPartial(MyPartialModel model)
{
return PartialView(model);
}
The model's got more than one property this time:
public class MyPartialModel
{
public string Name { get; set; }
public int Age { get; set; }
}
The partial's pretty much the same, except it now displays the new properties of the model.
#model MVCPlayGround.Models.MyPartialModel
#Html.TextBoxFor(m => m.Name)
#Html.TextBoxFor(m => m.Age)
The jquery on the main page/view is very also similar, but uses POST instead of GET.
// these could be anything, from control on the page, or whatever
var name = "James";
var age = 30;
$(document).ready(function () {
$('#load-partial').click(function () {
// note that Name and the Age are the names of the properties in our model
$.post('MyPartial', { Name: name, Age: age }).done(function (data) {
$('#section-b').html(data);
});
});
});
This works because when data transmitted via POST, it's treated as form data, and when the controller's deciding which action to use it'll look at the parameters for the actions, and compare them to the form data available. The MyPartialModel contains properties that match the form data, so it chooses that action. There are other subtle rules, but that's basically it. Behind the scenes it'll still be instantiating a model in the controller, it's just in the framework, not in the code you've written.
Another edit
Having just re-read your comment I don't think I've answered it fully.
If you want to save the changes you've made in a partial view to the main view, have some hidden fields in the main view to hold this data.
<input type="hidden" id="name-holder" />
<input type="hidden" id="age-holder" />
And then when you want to store a value to them, just set the values with jquery:
$('#some-save-button-maybe').click(function(){
$('#name-holder').val($('id-of-name-on-partial').val());
$('#age-holder').val($('id-of-age-on-partial').val());
});
When you click on a the button to show a partial, send the appropriate data to the controller to render in the partial:
$('#load-partial').click(function () {
$.post('MyPartial', { Name: $('#name-holder').val(), Age: $('#age-holder').val() }).done(function (data) {
$('#section-b').html(data);
});
});
Hopefully that's what you need...
Yes there are partial views in MVC, and they are usually belong in the Views/Shared folder of your project and are prefixed with a _ (i.e. _MyPartial.cshtml.
As #AdamHeeg pointed out in the comments, there are many tutorials on the web about this kind of setup and many different ways to achieve what you are after.
Here is roughly how I might tackle it...
HTML
<nav>
#Html.ActionLink("Button 1", "GetSectionB")
</nav>
<section id="sectionB">
<!-- Content here -->
</section>
JavaScript
$('nav a').on('click', function (e) {
e.preventDefault();
$.get(this.href, function (html) {
$('#sectionB').html(html);
});
});
Controller
public PartialViewResult GetSectionB()
{
var vm = new MyViewModel();
//do stuff
return PartialView("_SectionB", vm);
}
Hi i am making my project in the asp.net,
basic expected behaviour -- fill form name , select master module(dropdown), select sub modules(dropdown), ajax passes id of submodule dropdown, create(submit).. it will submit all values,
now code is behaves---- fill form name, select master and submodule, while selecting submodule from second dropdown is calling the ajax call, and create action is called, so the form name and masterID(that is extracted from first dropdown) gone blank... so i need to prevent the ajax call to call the controller
Myform in razor view
#using (Html.BeginForm())
{
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Form</legend>
<div class="editor-label">
#Html.LabelFor(model => model.FormName)
</div>
<div class="editor-field">
#Html.EditorFor(model => model.FormName)
#Html.ValidationMessageFor(model => model.FormName)
</div>
<select id="State" name="state"></select><br />
<p>
<input id="sbmt" type="submit" value="Create" />
</p>
</fieldset>
}
<div>
#Html.ActionLink("Back to List", "Index")
</div>
My ajax call
$('#State').change(function () {
var a = $('#State').val();
var token = $('[name=__RequestVerificationToken]').val();
$.ajax({
url: "/form/create",
type: "POST",
data: { __RequestVerificationToken: token, 'SubID': a }
});
});
My controller
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(Form form, int SubID)
{
if (ModelState.IsValid)
{
form.CreatedBy = 1;
form.SubId = SubID;
form.CreatedDate = DateTime.Now;
form.ModifyBy = 1;
form.ModifyDate = DateTime.Now;
form.IsActive = true;
form.IsDeleted = false;
db.Forms.Add(form);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.MasterID = new SelectList(db.Departments, "MasterId", "ModuleName", form.MasterID);
return View(form);
}
From the comments, you want to be able to post back the value of the selected state when you submit the form. The best approach would be to use a view model that includes the property SubId and bind your dropdownlist to that property (the SubId parameter in you POST method is then not necessary.
#Html.DropDownListFor(m => m.SubId, ....)
The alternative is to rename the control to SubId so it matches the parameter in your POST method
<select name="SubId" ...>
and delete the unnecessary javascript function $('#State').change(function () {...
I guess the easiest way for you would be to use MVC's ajax helpers. Change your form like so:
#using (Ajax.BeginForm("Create", "Home", null, new AjaxOptions { OnSuccess = "OnSuccess" }))
{
...
And afterwards add a javascript handler for onsuccess
function OnSuccess(){
alert("success");
}
This is barely functional code just to get you started.
PS. Make sure you add a reference to ~/Scripts/jquery.unobtrusive-ajax.min.js
I am using Html.BeginFrom ... to create a from Tag and Submit request to use external login providers.
The HttpPost action in Account Controller
//
// POST: /Account/ExternalLogin
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public ActionResult ExternalLogin(string provider, string returnUrl)
{
return new ExternalLoginResult(provider, Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
}
I need to send the RetunUrl and the Provider to the above action method
Currently i am creating Multiple forms using a Foreach with Razor
#foreach (ExternalLoginViewModel loginViewModel in Model)
{
using (Html.BeginForm("ExternalLogin", "Account", new { Provider = loginViewModel.AuthenticationClientData.DisplayName, ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post))
{
#Html.AntiForgeryToken()
<a class="#loginViewModel.AnchorCssClass" style="#loginViewModel.AnchorCssStyle" href="#">
<div class="#loginViewModel.DivCssClass" style="#loginViewModel.DivCssStyle">
<span aria-hidden="true" class="#loginViewModel.IconCssClass"></span>
</div>
</a>
}
}
But i think it can be done using a single from but i dont know how i can provide the Provider value which varies with the anchorTag Something like :
using (Html.BeginForm("ExternalLogin", "Account", new { Provider = "<SomeValue>", ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post))
{
#Html.AntiForgeryToken()
#foreach (ExternalLoginViewModel loginViewModel in Model)
{
<a class="#loginViewModel.AnchorCssClass" style="#loginViewModel.AnchorCssStyle" href="#">
<div class="#loginViewModel.DivCssClass" style="#loginViewModel.DivCssStyle">
<span aria-hidden="true" class="#loginViewModel.IconCssClass"></span>
</div>
</a>
}
}
Javascript used in the earlier case is (it works fine)
<script type="text/javascript">
$(document).ready(function() {
$(document).on("click", ".CSSclassonAnchor", function (e) {
e.preventDefault();
var form = $(this).closest("form");
form.submit();
});
});
</script>
I think its somehow will be posssible to post data using an anchor Tag
Any help in this regard will be great.. Thanks
one way of doing it is adding a hidden field to the form, and populate it from javascript. In your view modify the BeginForm to no include Provider parameter and add a <input type="hidden" /> in the form:
using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post))
{
#Html.AntiForgeryToken()
#Html.Hidden("Provider", "", new {id=hdnprovider})
#foreach (ExternalLoginViewModel loginViewModel in Model)
{
<a class="#loginViewModel.AnchorCssClass" style="#loginViewModel.AnchorCssStyle" href="#" data-name="#loginViewModel.AuthenticationClientData.DisplayName">
<div class="#loginViewModel.DivCssClass" style="#loginViewModel.DivCssStyle">
<span aria-hidden="true" class="#loginViewModel.IconCssClass"></span>
</div>
</a>
}
}
Then in Javascript use the data-name attribute of the link clicked and assign it to the hidden:
$(document).ready(function() {
$('a[data-name]').click(function (e) {
e.preventDefault();
var form = $(this).closest("form");
$("#hdnprovider").val($(this).data("Name"));
form.submit();
});
});
As the hidden has the name "Provider" it will be automatically binded to "Provider" parameter in your controller.