Why won't the ASP.NET Webform LinkButton in my MVC project invoke its code-behind OnClick event handler? - asp.net-mvc

I have a previously operational webforms project I had to include in a preexistent MVC-based solution and in it there's a LinkButton control inside a form that is now only partially working; its JavaScript event handler works perfectly fine (referenced below by OnClientClick) but the C# code-behind (lnkSubmit_Click) isn't being invoked! Why not?
My LinkButton's inside Pay.aspx:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Pay.aspx.cs" Inherits="PayUp.Pay" MasterPageFile="~/Views/Shared/Site.Master" %>
<form id="form1" runat="server" onsubmit="return validateForm();" defaultbutton="lnkSubmit" action="~/Views/Home/Pay.aspx" method="post" >
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div align="center">
<script type="text/javascript">
window.onload = function () {
hideFields();
};
</script>
<asp:UpdatePanel runat="server" id="PendingPayments1">
<ContentTemplate>
<!-- Valid form controls, blah blah.... -->
</ContentTemplate>
</asp:UpdatePanel>
<asp:Label ID="labelPayPlan" runat="server" Text="Pay Plan">
</asp:Label>
<asp:HiddenField ID="hiddenPDFForm" Value="false" runat="server" ClientIDMode="Static" />
<asp:UpdatePanel runat="server" id="PaymentInformation1">
<ContentTemplate>
<asp:LinkButton ID="lnkSubmit" runat="server" EnableViewState="false" OnClientClick="javascript: document.getElementById('hiddenPDFForm').value = 'false';"
CssClass="button" onclick="lnkSubmit_Click" onserverclick="lnkSubmit_Click" ClientIDMode="Static">Pay Up!<img alt='Pay Up!' src='images/pay.gif' style='border:0px; margin-left:6px;' />
</asp:LinkButton>
</ContentTemplate>
</asp:UpdatePanel>
</form >
The code-behind does exist inside Pay.aspx.cs:
using System;
using System.Web;
using System.Web.UI.WebControls;
using System.Configuration;
using SupportingMVCProject;
using System.Web.Mvc;
namespace PayUp
{
public partial class Pay : System.Web.Mvc.ViewPage<SupportingMVCProject.Account>
{
protected void Page_Load(object sender, EventArgs e)
{
// The code in this event handler runs just fine when I start the project!
// This code successfully receives and correctly parses my URL parameters (QN, PN, AC).
}
protected void lnkSubmit_Click(object sender, EventArgs e)
{
// The code in this event handler never gets to run!
}
}
}
My RouteConfig.cs looks like:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Http;
namespace MainMVCProject
{
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.IgnoreRoute("{WebForm}.aspx/{*pathInfo}");
routes.MapRoute("PayUpIndex", "SupportingMVCProject/PayUp",
new { controller = "PayUp", action = "Index" }
);
// Other valid preexisting MVC routes...
// blah, blah
}
}
}
The PayUpController.cs PayUpIndex route identified above looks like the following, and it does run:
public ActionResult Index(string QN, string PN, string AC)
{
string result = "";
if (!AccessValidation(PN, out result))
{
return RedirectToAction(result);
}
// blah blah
ViewData["message"] = "QN=" + QN + "PN=" + PN + "AC=" + AC;
return this.View("~/Views/PayUp/Pay.aspx");
}
My start URL is http://localhost:3835/SupportingMVCProject/PayUp?QN=ABC-1234567&PN=ABC1234567&AC=123456789. It launches the page just fine and all controls are interactive, all except my "Pay Up!" button (lnkSubmit). Why is lnkSubmit_Click inside Pay.aspx.cs not being invoked?
Your insight is greatly appreciated!

I am pretty sure I have read somewhere that if you use OnClientClick then server side code will not run unless you make some changes
Check out the below link
OnclientClick and OnClick is not working at the same time?

Related

Nothing happens and no errors binding data from sql server to textbox

Im trying tot start with a easy setup. I try to get de data into textboxes and start with the first step. For some reason I can't bind the data to the textbox and don't received any errors. Programming is running fine, but nothing is happening when I press the button.
I tested with gridview to check the connection and that seems to be working.
I'm using MS SQL Server 2016 Express version, visual studio 2017, ASP and C#
What do I wrong? Wrong code? Connection blocked by the server?
.........................
ASPX code:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="test3.aspx.cs" Inherits="test3" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:TextBox ID="TextBox1" runat="server" Width="281px"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="Start" />
</div>
</form>
</body>
</html>
.............................
The CS code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data.SqlClient;
using System.Configuration;
public partial class test3 : System.Web.UI.Page
{
public SqlConnection conn = new SqlConnection(#"Data Source=.\WDVEXPRESS;Initial Catalog=user;User ID=testaccount;Password=123test");
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Button1_Click(object sender, EventArgs e)
{
SqlCommand com;
string str;
conn.Open();
str = "select * from Company$ where Name = 'testuser'";
com = new SqlCommand(str, conn);
SqlDataReader reader = com.ExecuteReader();
if (reader.Read())
{
TextBox1.Text = reader["Name"].ToString();
reader.Close();
conn.Close();
}
}
}
.......................
Many thanks for the help!
Your button on aspx page is not bound to button click event on aspx.cs page. Check below code it will tell you how they got bounded -
HTML ( ASPX PAGE ) CODE
<asp:Button ID="Button1" runat="server" Text="Start" OnClick="Button1_Click" />
CS CODE
protected void Button1_Click(object sender, EventArgs e)
{
//Your Click Event Here
}

$.get() and $.post() in MVC app works fine in local Cassini webserver but when published into IIS 7.5 it doesn't work anymore

I'm actually stuck on this MVC application and can't find out the cause.
The code works fine in local Vis Studio 2013 Cassini webserver.
Hence when I type the URL in the browser: "/Customer/EnterCustomerDetails"
then I'm displayed a simple form, a DIV tag containing status message "Loading..." and after 5 seconds some data via EF is returned due to the $.get() script that gets executed.
However, when I publish the same code into IIS 7.5 running inside Windows 7 Ultimate, then all I see is the form and only the div tag that displays the message "Loading..." but no data is displayed and it seems the $.get() is not working in the full blown IIS and neither is $.post().
Where am I going wrong? Any help much appreciated. Thanks in advance.
"EnterCustomerDetails.cshtml"
#model P10LearnNewMVCWithEF.ViewModel.CustomerViewModel
#using P10LearnNewMVCWithEF.Models
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>EnterCustomerDetails</title>
#*BELOW Weve IMPORTED the 3 important JQuery LIBRARIES, since we want to use the $.get() AJAX method*#
<script src="~/Scripts/jquery-1.8.3.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
<div>
<form id="frm1">
Customer Code:- #Html.TextBoxFor(m => m.Customer.CustomerCode)
#Html.ValidationMessageFor(x => x.Customer.CustomerCode) <br />
Customer Name:- #Html.TextBoxFor(m => m.Customer.CustomerName)
#Html.ValidationMessageFor(x => x.Customer.CustomerName) <br />
<input type="button" value="Submit via true AJAX" id="btn1" onclick="SendData()" />
</form>
<div id="status"></div>
<table id="tbl">
<tr><th>Customer Code</th><th>Customer Name</th></tr>
</table>
<script type="text/javascript">
$("#status").text("Loading..."); //Add STATUS MESSAGE "Loading..." to DIV. Must use ".text" and NOT ".val"
//Making a CALL to the "GetCustomers" ACTION within the "Customer" CONTROLLER and Results returned will be in "BindData"
$.get("GetCustomers", null, BindData);
// The "GetCustomers" ACTION will return the JSON data into this JavaScript function
function BindData(customers) {
var tbl = $("#tbl");
for (var i = 0; i < customers.length; i++) {
var newRow = "<tr>" +
"<td>" + customers[i].CustomerCode + "</td>" +
"<td>" + customers[i].CustomerName + "</td>" +
"</tr>";
tbl.append(newRow);
}
$("#status").text(""); //REMOVING STATUS MESSAGE to EMPTY
}
function SendData() {
$("#status").text("Adding data via ajax..."); //Add STATUS MESSAGE "Loading..." to DIV. Must use ".text" and NOT ".val"
var frm = $("#frm1").serialize();
$.post("Submit", frm, BindData);
$("#Customer_CustomerCode").val("");
$("#Customer_CustomerName").val("");
}
</script>
</div>
</body>
</html>
"CustomerController.cs"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using P10LearnNewMVCWithEF.DAL; //"CustomerDal" in here which derives from "DbContext"
using P10LearnNewMVCWithEF.Models; //"Customer" class in here
using P10LearnNewMVCWithEF.ViewModel;
namespace P10LearnNewMVCWithEF.Controllers
{
public class CustomerController : Controller
{
//Below is our NEW Simplified ACTION that will simply display our Enter Customer Details UI
public ActionResult EnterCustomerDetails()
{
CustomerViewModel objCustomerViewModel = new CustomerViewModel();
objCustomerViewModel.Customer = new Customer(); //This code by SHIV is pretty useless
//NOTE - WE'RE NOT RETRIEVING ANY DATA FROM DATABASE ANYMORE! as we'll do that with "GetCustomers()" ACTION
return View("EnterCustomerDetails", objCustomerViewModel);
}
public ActionResult Submit()
{
Customer obj = new Customer();
obj.CustomerCode = Request.Form["Customer.CustomerCode"]; //"name" is used on Server-side. "id" is used in Client-side.
obj.CustomerName = Request.Form["Customer.CustomerName"];
CustomerDal dal = new CustomerDal();
if (ModelState.IsValid)
{
//Let's INSERT the new Customer into DB via EF
dal.Customers.Add(obj);
dal.SaveChanges();
}
List<Customer> customersColl = dal.Customers.ToList<Customer>(); //Return all data from tCustomer via EF
return Json(customersColl, JsonRequestBehavior.AllowGet); //make sure you say customersColl AND NOT “customersColl”
}
//Below: "GetCustomers()" ACTION will be called by $.get() and simply returns a Collection of JSON data
public ActionResult GetCustomers()
{
CustomerDal dal = new CustomerDal();
List<Customer> customerscoll = dal.Customers.ToList<Customer>();
Thread.Sleep(5000);
return Json(customerscoll, JsonRequestBehavior.AllowGet);
}
}
}
Posting this as an answer so that you can mark it as answered.
That sounds like the identity in your IIS app pool is not authorized for database access. Either assign a new identity that has permission, or grant access to the identity you are using.

MVC CORS works in IE but not in Chrome

I'm stuck with a CORS issue which works totally fine when I'm using Internet Explorer, but doesn't work with Google Chrome.
I have 2 separate projects in Visual Studio 2013: PROJECT 1 is on port 1044, it's just an empty project containing an HTML page with a Button which uses AngularJS to make a call to ACTION GetCustomer residing inside PROJECT 2 on port 1042. The ACTION then returns JSON data back to PROJECT 1.
The cross domain call works fine when the Button is clicked in IE and returns the data back to the HTML TextBox saying "ShivDataFromServer". But the same doesn't happen in Chrome.
PROJECT 1 on port 1044:
HomePage.html:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<script src="angular.min.js"></script>
<!--<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>-->
<body>
<script type="text/javascript" src="CustomerViewModel.js"></script>
<div ng-app>
<!-- Below is our VIEW i.e. Display-->
<div id="ViewCustomer" ng-controller="MyController">
Customer Name: <input type="text" id="txtCustomerName" ng-model="Customer.Name" /> <br />
Customer Amount: <input type="text" id="txtCustomerAmount" ng-model="Customer.Amount" /> <br />
<div style="width : 242px; height : 26px; background-color : {{CustomerView.Color}}"></div> <br />
<input type="button" id="btn1" value="Get data from Server" ng-click="GetData()" />
</div>
</div>
</body>
</html>
CustomerViewModel.js:
function MyController($scope, $http) {
$scope.Customer = { "Name": "ShivHardCodedData", "Amount": "1000" };
$scope.CustomerView = { "Color": "" };
//BELOW IS TRANSFORMATION LOGIC! Depending on Amount it will be GREEN or RED meaning "danger".
$scope.$watch("Customer.Amount", function() {
if ($scope.Customer.Amount < 1000) {
$scope.CustomerView.Color = "Green";
} else {
$scope.CustomerView.Color = "Red";
}
}
);
$scope.GetData = function () {
//BELOW WORKS!!
$http({ method: "GET", url: "http://localhost:1042/Customer/GetCustomer" })
.success(function (data, status, headers, config) { $scope.Customer = data; })
.error(function (data, status, headers, config) { });
} //END OF "GetData() function"
}
PROJECT 2 which is an MVC project on port 1042:
CustomerController.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using P10JsonJQuery_httpService.Models;
namespace P10JsonJQuery_httpService.Controllers
{
public class CustomerController : Controller
{
[ImAllowingCors]
public ActionResult GetCustomer()
{
Customer objCustomer=new Customer();
objCustomer.Name = "ShivDataFromServer";
objCustomer.Amount = 1000;
return Json(objCustomer, JsonRequestBehavior.AllowGet);
}
}
//CORS (Cross Origin Resource Sharing). I've made up name "ImAllowingCors" but ending "Attribute" is C# KEYWORD
public class ImAllowingCorsAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
//This means ALLOW any calls from a Cross-domain (i.e. allow calls from different server)
filterContext.RequestContext.HttpContext.Response.AddHeader("Access-Control-Allow-Origin", "*");
base.OnActionExecuting(filterContext);
}
}
}
ie does not count calls on different ports, but the same domain as being cross origin, whereas Chrome does. Thus, you need to set it up for chrome to allow this.
To do it the way you are trying, you will need to make sure the custom filter is registered and I think you will also need to change your attribute to [ImAllowingCorsAttribute]:
See: similar issue
You will need to allow Cors for your app. Something like the following annotation above the action:
[EnableCors(origins: "http://localhost:1042", headers: "*", methods: "*")]
Perhaps put a breakpoint in your attribute, as I doubt it is being hit. This should show you how to enable cors:
enabling Cors

Convert simple ASP.NET WebForm to MVC

I have simple asp.net page:
using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
rptTable.DataSource = GetDataFromDB();
rptTable.DataBind();
}
}
private DataTable GetDataFromDB()
{
DataTable table = new DataTable();
table.Columns.Add("Id", typeof(int));
table.Columns.Add("Name", typeof(string));
table.Rows.Add(1, "HDD");
table.Rows.Add(2, "Video");
table.Rows.Add(3, "RAM");
return table;
}
protected void rptTable_ItemCommand(object source, RepeaterCommandEventArgs e)
{
TextBox tbName = (TextBox)e.Item.FindControl("tbName");
int id = Convert.ToInt32(e.CommandArgument);
string name = tbName.Text;
//Category.Save(int id, string name)
//Rebuild Repeater
}
}
and aspx code:
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" EnableEventValidation="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table>
<asp:Repeater ID="rptTable" runat="server" OnItemCommand="rptTable_ItemCommand">
<ItemTemplate>
<tr>
<td>
<%#Eval("id")%>
</td>
<td>
<asp:TextBox ID="tbName" runat="server" Text='<%#Eval("Name")%>'></asp:TextBox>
</td>
<td>
<asp:Button ID="btnSave" runat="server" Text="Save" CommandArgument='<%#Eval("id")%>' />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</div>
</form>
</body>
</html>
It works like simple grid and you are able to edit data directly in the grid.
How can I implement same logic in MVC ?
Thanks!
To replicate the asp:Repeater functionality in an MVC application you would normally use a foreach loop with textboxes within bound to model properties.
You can however if you really want, include an asp:repeater control in an MVC app, but it's not going to work as you'd expect if it relies on postbacks.
If it's a simple read only control, you can put something like the following in your view:
<scipt runat="server">
protected void Page_Load(object sender, EventArgs e) {
rptTable.DataSource = ViewData["yourViewDataList"];
rptTable.DataBind();
}
</script>
This assumes you've got something in the ViewData which can be databound, so to do that you'd likley need to create a controller method to build your DataTable as you've done in 'GetDataFromDB()'
I'm not going to go into the full implementation but at a high level, that's how you could use the control in MVC.

Is jquery.validate.unobtrusive Bugged?

I am trying to get my clienside validation to work when using an ajax request in a jquery ui dialog.
This means I have no submit button and I do no post back. I could not figure out why I could not get it to work.
I posted this question . I been playing around with it can come to the conclusion is that for whatever reason I need to load up the jquery.validate.unobtrusive with my partial view. It makes no sense to me.
Is this a bug?
Edit
I also gone and posted the error on the asp.net codeplex
The added benefit to this is that if you wish you can just download my little sample application and try it out.
Or you can Follow these steps
Make an non empty asp.net mvc 3 application( I am using razor)
_Layout.cshtml
#ViewBag.Title
<script type="text/javascript">
$(function ()
{
$.get('/home/dialog', null, function (r)
{
var a = $("#dialog").dialog({
resizable: false,
height: 500,
modal: true,
buttons: {
"Delete all items": function ()
{
$('#testFrm').validate().form();
},
Cancel: function ()
{
$(this).dialog("close");
}
}
}).html(r);
});
$('#testFrm').live('submit',function (e)
{
e.preventDefault();
});
});
</script>
</head>
<body>
<div class="page">
<div id="header">
<div id="title">
<h1>My MVC Application</h1>
</div>
<div id="logindisplay">
#Html.Partial("_LogOnPartial")
</div>
<div id="menucontainer">
<ul id="menu">
<li>#Html.ActionLink("Home", "Index", "Home")</li>
<li>#Html.ActionLink("About", "About", "Home")</li>
</ul>
</div>
</div>
<div id="main">
#RenderBody()
<div id="footer">
</div>
</div>
</div>
</body>
</html>
ViewUserControl1 (Partial View) - Stick in Home View folder
#model MvcApplication1.Models.TestModel
#using (Html.BeginForm("test","Account",FormMethod.Post,new {#id="testFrm"}))
{
#Html.ValidationSummary()
#Html.TextBoxFor(x => x.Name)
}
Index (should exist replace with this)
#model MvcApplication1.Models.TestModel
#{
ViewBag.Title = "Home Page";
}
<h2>#ViewBag.Message</h2>
<p>
To learn more about ASP.NET MVC visit http://asp.net/mvc.
</p>
#DateTime.Now
<div id="dialog">
</div>
note the dialog id this will be where the ajax request of the partial view gets stored
Home Controller
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult test()
{
return null;
}
public PartialViewResult Dialog()
{
return PartialView("ViewUserControl1");
}
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
}
}
TestModel.cs // view model
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.ComponentModel.DataAnnotations;
namespace MvcApplication1.Models
{
public class TestModel
{
[Required()]
public string Name { get; set; }
}
}
web.config
<appSettings>
<add key="webpages:Enabled" value="false" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
</appSettings>
Now run the application. Click "Delete all items" and "Submit Query".
Nothing should happen. No validation pops up for me.
Now go and add this line to the Partial View(ViewUserControl1)
<script src="../../Scripts/jquery.validate.unobtrusive.js" type="text/javascript"></script>
#model MvcApplication1.Models.TestModel
#using (Html.BeginForm("test","Account",FormMethod.Post,new {#id="testFrm"}))
{
#Html.ValidationSummary()
#Html.TextBoxFor(x => x.Name)
<input type="submit" />
}
Now try again.
It should now come up with validation errors.
I think I found some sort of a work around. Even though I think a automatic way should be done for something so basic as making the validation work with partial views
Work around
This is not a bug. When you load a PartialView using Ajax, you must then parse the unobtrusive validation attributes included in the new elements you are loading.
See http://forums.asp.net/t/1651961.aspx/1?Unobtrusive+validation+not+working+on+form+loaded+by+Ajax

Resources