Submit vs Submit & Close buttons - asp.net

On my "Create" view for my model, I'd like a "Submit" button as well as a "Submit & Close" button. I was looking at the answer to this question for information on how to close a page from a controller action (although I see some comments saying that this isn't possible--is there a workaround for that?).
These are the buttons currently:
#using (Html.BeginForm())
{
#Html.HiddenFor(model => model.Project.ProjectID);
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="save-buttons">
#if (Model.ReadOnly)
{
<button type="button" id="close_page" onclick="closeWindow();">Close</button>
}
else
{
<button type="submit">Save Project</button>
if (Model.Project == null)
{
<button type="button">Delete Project</button>
}
else
{
<button type="button" onclick="deleteProject(#Model.Project.ProjectID, #Model.Project.SubmissionNumber);">Delete Project</button>
}
<button type="button">Save & Close</button>
}
</div>
... the form itself is below here
and the submit action is:
public ActionResult Create([Bind(Include = "ProjectName,ProjectDescription,DateReceived,EffectiveDate,ExpirationDate,GeneralContractor,ProjectTerm,ProjectType,SubmissionNumber,PolicyNumber,Status,Underwriter,Division,BrokerCity,TAName,Branch,FirstNamedInsuredAddress,FirstNamedInsured,ProjectAddress")] Project project)
{
if (ModelState.IsValid)
{
if (project.ProjectID <= 0)
{
db.Projects.Add(project);
}
else
{
db.Entry(project).State = EntityState.Modified;
}
db.SaveChanges();
return RedirectToAction("Create", new { sub_num = project.SubmissionNumber });
}
var model = new ProjectViewModel()
{
Project = db.Projects.Find(project.ProjectID),
States = GetSelectListItems(GetAllStates()),
Branches = GetSelectListItems(GetAllBranches()),
Divisions = GetSelectListItems(GetAllDivisions()),
ProjectTypes = GetSelectListItems(GetAllProjectTypes()),
Statuses = GetSelectListItems(GetAllStatuses()),
ReadOnly = false,
Cleared = false,
EditMode = false
};
return View("Maintenance", model);
}
My problem comes with differentiating which button sent the browser to the submit method. I've come up with a few different possibilities but I'm not sure if any of them are possible (I don't think they are):
First is to create a boolean model property that is true when the page should close after submitting and false otherwise. Then I can wrap my RedirectToAction in an if statement like so:
if (Model.Done) {
return JavaScript("window.close();");
}
else
{
return RedirectToAction("Create", new { sub_num = project.SubmissionNumber });
}
But I don't know how I could set this property on button click. I don't think this is possible so I can't do this but correct me if I'm wrong.
The other possibility would be to pass an argument to the action when the button is clicked, but I don't know how to do this when it is a <button type="submit"></button>.
Does anyone have any suggestions? Thanks!

Hope this may help you
You can can set name of button.If click on that button then we can get which button is clicked.
In Create.cshtml
<button type="submit" id="Create" name="Create"></button>
<button type="submit" id="Close" name="Close"></button>
In Controller.cs
Public ActionResult Create(string name){
if(name="Create")
{
//here code for create button
return RedirectToAction("Create", new { sub_num =project.SubmissionNumber });
}
if(name="Close")
{
//heere code for close button
return JavaScript("window.close();");
}
}

Related

How to get the dynamic button's id ASP.Net Core

I am trying to find a way to send the id of the clicked button to the backend. The problem is that I am creating lots of buttons with one method but the id is different.
#foreach (var item in Model.showManager.GetMovies())
{
i++;
#if (Model.user.IsAdmin == true)
{
<input class="btn_confirm" type="submit" id=i value="Delete"/>
}
}
The point is that every button is created with different id and I want to send that id to the backend.
Update
My demo is a MVC project, I have a DynamicButtonController and a Index view:
DynamicButtonController:
public class DynamicButtonController : Controller
{
public IActionResult Index()
{
return View();
}
[HttpPost]
public IActionResult Index(int id)
{
return View();
}
}
Index view :
#for (var i = 0; i < 5;i++ )
{
<input class="btn_confirm" type="submit" id=#i value="Delete" />
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.1/jquery.min.js"></script>
<script>
$(".btn_confirm").click(function()
{
var data = (this).id;
$.ajax({
type: "POST",
url: '/DynamicButton/Index/',
data: { id: data }
});
});
</script>
result:
If you use Razor pages, you can refer to the below demo,use asp-route-id="#i"
ButtonIdModel:
public class ButtonIdModel : PageModel
{
public void OnGet()
{
}
public void OnPost(string id)
{
}
}
ButtonId.cshtml:
#page
#model yourproject.Pages.ButtonIdModel
<form method="post">
#for (var i = 0; i < 5;i++ )
{
<input class="btn_confirm" type="submit" id=#i value="Delete" asp-route-id="#i" />
}
</form>
The point is that every button is created with different id and I want
to send that id to the backend.
Well, based on your issue, you want to bind all the button ids then want to pass those Ids in your backend.
However, another answer has guided you how to pass id to your controller. Nonetheless, it doesn't resolve your main concern that is how to pass the list of ids on button submit.
Algorithm:
As said earlier, first you have to get the list of button ids which has been generated from your foreach loop and you have to push them in an array, finally need to pass those in your controller (backend). Here, importantly you have to keep in mind, it doesn't matter how the button been generated, for loop or foreach loop the fact is your button should have class name of same type and the ids for instance: class="myBtnClass btn btn-danger" and id="btnId:#i"
Solution:
View:
#{
ViewData["Title"] = "ViewGetDynamicButtonsID";
}
<div>
#for (var i = 1; i < 5; i++)
{
<input class="myBtnClass btn btn-danger" id="btnId:#i" value="Delete:#i" style="margin-bottom:2px" /> <br />
}
<input type="submit" id="btnSubmit" class="btn btn-success" value="Submit" />
</div>
#section scripts {
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.2.1.min.js"></script>
<script>
$(document).ready(function () {
$("#btnSubmit").on("click", function () {
var ids = [];
$(".myBtnClass").each(function () {
//Getting All Button Ids and Pusing in array
ids.push($(this).attr("id"));
});
$.ajax({
type: "POST",
url: 'http://localhost:5094/stuff/GetAllButtonId',
datatype: "json",
data: { buttonids: ids },
success: function (res) {
console.log(res);
alert("It works")
},
error: function () {
alert("It failed");
}
});
return false;
});
});
</script>
}
Controller:
public IActionResult CreateDynamicButton()// This is for loading the view
{
return View();
}
[HttpPost]
public IActionResult GetAllButtonId(List<string> buttonids) // This for submit the button request.
{
return Ok(buttonids);
}
Note: I have defined Button Ids as List<string> thus you can do it as your convenient type
Output:

BeginCollectionItem() gives only lastly appended item for PostBack

InquiryOrderViewModel
public class InquiryOrderViewModel
{
public InquiryOrder InquiryOrder { get; set; }
public List<InquiryOrderDetail> InquiryOrderDetails { get; set; }
}
InquiryOrderIndex View and the Script to add items
#model eKnittingData.InquiryOrderViewModel
#using (Html.BeginForm("Save", "InquiryOrder"))
{
<div id="editorRows">
#foreach (var item in Model.InquiryOrderDetails)
{
Html.RenderPartial("_DetailEditorRow", item);
}
</div>
#Html.ActionLink("Add another...", null, null, new { id = "addItem" })
<div class="col-md-6"> <input type="submit" value="Save" class="btn btn-success" /> </div>
}
<script>
$('#addItem').click(function (e) {
e.preventDefault();
var isExist = false;
$('.editorRow').each(function () {
if ($(this).children('.class01').val() == 0 || $(this).children('.class02').find("option:selected").text() == "Select") {
isExist = true;
return false;
}
});
if (isExist == false) {
$('.editorRow').each(function () {
$(".editorRow").children().attr("disabled", "disabled");
});
$.ajax({
url: '#Url.Action("BlankEditorRow", "InquiryOrder")',
cache: false,
success: function (data) {
$("#editorRows").append(data);
}
});
}
});
</script>
DetailEditorRow PartialView
#model eKnittingData.InquiryOrderDetail
#using eKnitting.Helpers
#using (Html.BeginCollectionItem("InquiryOrderDetails"))
{
<div class="editorRow">
#Html.DropDownListFor(a => a.ComponentId, (SelectList)ViewBag.CompList, "Select", new { Class = "class02" })
#Html.DropDownListFor(a => a.DesignCodeId, (SelectList)ViewBag.DCodeList, "Select", new { Class = "class03" })
#Html.TextBoxFor(a => a.NoOfParts, new { Class = "class01" })
delete
</div>
}
ActionResult which returns PartialView
public ActionResult BlankEditorRow()
{
var objContext = new KnittingdbContext();
ViewBag.CompList = new SelectList(objContext.Components, "ComponentId", "ComponentName");
ViewBag.DCodeList = new SelectList(objContext.DesignCodes, "DesignCodeId", "DesignCodeCode");
return PartialView("_DetailEditorRow", new InquiryOrderDetail());
}
ActionResult for 'GET'
var objContext = new KnittingdbContext();
var newIovm = new InquiryOrderViewModel();
var newIo = new InquiryOrder();
//initial item
var newIoD = new List<InquiryOrderDetail>
{
new InquiryOrderDetail()
};
newIovm.InquiryOrder = newIo;
newIovm.InquiryOrderDetails = newIoD;
ViewBag.CompList = new SelectList(objContext.Components, "ComponentId", "ComponentName");
ViewBag.DCodeList = new SelectList(objContext.DesignCodes, "DesignCodeId", "DesignCodeCode");
return View(newIovm);
ActionResult for 'POST'
public ActionResult Save(InquiryOrderViewModel inquiryOrderViewModel)
{
.................
}
When i click the add button im able to add items dynamically. But for PostBack it gives me only the lastly appended item. I checked it by putting a break point on post ActionResult. How can i get the whole collection for PostBack? Where did i go wrong? All help appreciated. Thanks!
Your scripts sets a variable var isExist = false;. When you add a new item, you check if the value is false (which it is if you got that far) and then disable all existing inputs.
Disabled form controls do not post back, hence you only get the values for the last row you have added.
Its unclear why you would want to disable them, but if you want to prevent editing of existing rows, the make them readonly
$(".editorRow").children().prop("readonly", true);

How do I pass an id of a clicked button to controller using AjaxBeginForm?

I'm using #Ajax.BeginForm() with KendoUI ListView in my asp.net mvc3 application. The KendoUI ListView displays a list of Items with a button for each item.
My requirement is that onclick of submit button, I need to send the id of a clicked button to the controller and return the full information of the Item.
My approach was to use onclick function for all buttons to trigger AjaxBeginForm submit input but the AjaxBeginForm submit input doesn't seems to pass the right value into the controller,
How can I achieve this?
<pre>
//My Ajax form
var ajaxOpts = new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "gallery",
InsertionMode = InsertionMode.Replace,
OnBegin = "OnBeginT1",
};
#using (Ajax.BeginForm("BlogInformation", ajaxOpts))
{
<input id="input" type="submit" style="display: none"/>
}
<script id="listview-template" type="x-kendo-template">
<button class="k-button1" onclick="returnsubmitted()" id="#:id#" name="but">Read More</button>
//Displaying a list
</div>
#(Html.Kendo().ListView<Blog>()
.Name("listView")
.TagName("div")
.ClientTemplateId("listview-template")
.DataSource(dataSource =>
{
dataSource.Read(read => read.Action("Blog_Read", "Blog"));
})
)
<script>
function returnsubmitted() {
//$("input").val($("#:id#").val());//This does not pass the right value to input
// $("#input").val($('.k-button1').attr('class').id);
$("#input").click();
}
</script>
//Here is my controller
[HttpPost]
public ActionResult BlogInformation(string blogid)
{
XElement element = XElement.Load(Server.MapPath("~/App_Data/Blogs.xml"));
IEnumerable<Blog> data = null;
if (!string.IsNullOrEmpty(blogid))
{
var xElement = FindByID(blogid, element.Element("Blog")).Element("Blog");
if (xElement != null)
{
data = FindByID(blogid, element.Element("Blog"))
.Element("items")
.Elements("Blog")
.Select(e => ToBlog(e));
}
else
{
data = element.Elements("Blog").Select(e => ToBlog(e));
}
}
return View(data);
}

Model values are null during [HttpPost]

I'm having some problems with my code and was hoping someone could give me a hand. Here's the snippet I'm working with:
[Authorize]
public ActionResult EventResults(int id)
{
List<Event> CompetitionEvents = Event.getEventsByCompetitionId(id);
ViewBag.CompetitionEvents = CompetitionEvents;
List<Person> Competitors = Competition.getCompetitorsByCompetitionID(id);
ViewBag.Competitors = Competitors;
List<Results> Results = Competition.getCompetitorResultsPairings(CompetitionEvents, Competitors);
ViewBag.Results = Results;
ViewBag.OrganizerEmail = Competition.getCompetitionById(id).OrganizerEmail;
return View();
}
#model BINC.Models.Results
#using BINC.Models;
#{
var eventList = ViewBag.CompetitionEvents as List<Event>;
var competitorList = ViewBag.Competitors as List<Person>;
var resultList = ViewBag.Results as List<Results>;
}
<h2></h2>
<p>Results:</p>
#using (Html.BeginForm())
{
foreach (var evt in eventList)
{
<fieldset>
<legend>#evt.activity.Name</legend>
<p>Event Description: #evt.activity.Description</p>
#foreach (var competitor in competitorList)
{
foreach (var result in resultList)
{
if (result.EventID == evt.id && result.CompetitorEmail == competitor.Email)
{
<p>Competitor: #competitor.FirstName #competitor.LastName</p>
<p>Score: #result.Score</p>
if (ViewBag.OrganizerEmail.Equals(#User.Identity.Name))
{
#Html.LabelFor(model => model.Score, "New Score ");
#Html.TextBoxFor(model => model.Score, new { maxlength = 10, style = "width:125px" })
<input type="submit" name="submitButton" value="Update" />
}
}
}
}
</fieldset>
}
}
[HttpPost]
public ActionResult EventResults(Results res)
{
//stuff
}
My problem is nothing other than the score is set on my Results object.
For example, when I put the value '15' into the text box and click 'Update', I'm passing the Result model object to the httppost method, which has everything set to null other than the 'score' field that I just entered.
Am I over complicating this? Is there an easier way?
I tried adding
#Html.HiddenFor(model => model.EventID);
#Html.HiddenFor(model => model.CompetitorEmail);
but that didn't seem to help any.
You are having multiple Submit buttons and that could be the issue, also this is not considered as good practise
<input type="submit" name="submitButton" value="Update" />
keep just one submit button at the end of the form
Basically-- make sure you pass the model to view-- and use the Html Helpers (ie TextBoxFor() and HiddenFor)
I don't think it's an issue with the submit button-- but the one thing that would probably help is to actually pass the model to the view. You are using the ViewBag to pass your data. Pass the model to View and your Html Helpers should generate the correct form names in order for the model binding to work.

MVC 1.0 Ajax.BeginForm() submit inside an Html.BeginForm()

I have a View for creating a new account in my application. This view starts with Html.BeginForm() and hits the right controller (Create) no problems.
I decided to add an Ajax.BeginForm() so that I could make sure an account with the same name doesn't already exist in my application.
When I click the submit using either button it goes to the same controller (Create). To try and differentiate which submit button was clicked, I put in a check to see if the request is Ajax then try to run a different code path. But Request.IsAjaxRequest() doesn't fire. What is my best bet to implement this functionality in an existing form with MS Ajax?
<% using (Html.BeginForm()) {%>
..............
<% using(Ajax.BeginForm("Echo",
new AjaxOptions() { UpdateTargetId = "EchoTarget" }))
{ %>
Echo the following text:
<%=Html.TextBox("echo", null, new { size = 40 })%>
<input type="submit" value="Echo" />
<% } %>
<div id="EchoTarget">
controller code:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(User newUser)
{
if (Request.IsAjaxRequest())
{
return Content("*you hit the ajax button");
}
else
{ //regular create code here.....
}
</div>
If you insist on multiple form usage..use Javascript in a some function like this
<SCRIPT>
function InnerFormSubmitter(dataForm, actionForm) {
actionForm.innerHTML = dataForm.innerHTML;
actionForm.submit();
}
</SCRIPT>
<form name="yourButton" action="ValidateSomething" method="post"></form>
<form name="mainForm" action="SavedData" method="post">
<input type="textbox" name="text1">
<input type="textbox" name="text2">
<button name="validateUserButton" id="FormButton" onChange=
"InnerFormSubmitter (this.form, document.getElementById('yourButton'))">
</button>
</form>
Hope this helps!
Addendum on jQuery usage for your scenario:
Since you wanted a link:
Check Availability
function isValidUser(userId) {
var url = "<CONTROLLER>/<ACTION>/" + userId;
$.post(url, function(data) {
if (data) {
// callback to show valid user
} else {
// callback to show error/permission
}
});
}
And you controller should have:
[AcceptVerbs("POST")]
public bool IsValidUser(int id) {
// check availability
bool allow = CheckUser();
// if allow then insert
if (allow) {
//insert user
return true;
} else {
return false;
}
}
Further Update on jQuery:
Instead of
document.getElementById('UserIdent').value
you can use
$('#UserIdent').val();
Update on JSON usage
The JsonResult class should be used in the Controller and $.getJson function in the View.
$(function() {
$('#yourLinkOrButton').click(function() {
$.getJSON("<CONTROLLER>/GetUserAvailability/", null, function(data) {
$("#yourDivorLablel").<yourFunctionToUpdateDiv>(data);
});
});
public JsonResult GetUserAvailability()
{
//do all validation and retrieval
//return JsonResult type
}
You cannot nest forms, ever, in any HTML page, no matter how you generate the form. It isn't valid HTML, and browsers may not handle it properly. You must make the forms siblings rather than children.

Resources