MVC Ajax form with unobstructive validation errors not going away - c#

I am having an issue where form errors are persisting on the page even after the form is valid.
I have the following setup:
_Layout.cshtml:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>#ViewBag.Title</title>
<link href="#Url.Content("~/Content/Site.css")" rel="stylesheet" type="text/css" />
<script src="#Url.Content("~/Scripts/jquery-1.5.1.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/modernizr-1.7.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/MicrosoftAjax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/MicrosoftMvcAjax.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="#Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" type="text/javascript"></script>
</head>
<body>
#RenderBody()
</body>
</html>
index.cshtml:
#model SimpleForm.Models.Name
#{
ViewBag.Title = "Form";
}
<script>
$().ready(function () {
$("#quote_form").submit(function () {
return true;
});
});
</script>
#using (Ajax.BeginForm("RunQuote", "Page", new AjaxOptions { UpdateTargetId = "quoteSummary" }, new { id = "quote_form", onreset = "return confirm('Clear all form data?')" }))
{
<input type="submit" value="Send" />
<fieldset>
<legend>Name </legend>
<dl>
<dt>First</dt>
<dd>#Html.TextAreaFor(m => m.first, new { onblur = "$('#quote_form').submit();" })</dd>
<dt>Last</dt>
<dd>#Html.TextAreaFor(m => m.last, new { onblur = "$('#quote_form').submit();" })</dd>
</dl>
</fieldset>
<div class="qMatrixSubText">
#Html.ValidationSummary()
#{
Html.ValidateFor(m => m.first);
Html.ValidateFor(m => m.last);
}
</div>
<div id="quoteSummary" class="quoteSummary">
</div>
}
FormController.cs
using System;
using System.Web.Mvc;
using SimpleForm.Models;
namespace SimpleForm.Controllers
{
public class FormController : Controller
{
//
// GET: /Form/
public ActionResult Index()
{
return View();
}
public String RunQuote(Name quote)
{
return "Success!";
}
}
}
Name.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;
namespace SimpleForm.Models
{
public class Name
{
[Required()]
public string first { get; set; }
public string last { get; set; }
}
}
The form populates fine, I see the error if I don't put anything into first and the form won't submit. After populating something into first I get the ajax call and then it posts "Success" to the div.
However, this is the problem, the error "the first field is required." still remains on the page. It's as if the ajax submit form is going through before the validation gets a chance to clear the error, and then it never gets the chance.
Any way to get the validation to still remove the errors?

The form is not being validated, because your onblur event is short-circuiting the submission process in jquery-unobtrusive-ajax.js.
Instead, change your onblur event for both fields to the following:
$(this).parents('form:first').find(':submit')[0].click();
This will invoke the jquery.unobtrusive-ajax.js script, causing validation to occur prior to the Ajax submission to the server.
UPDATE
When I looked back at your view, I saw that you are calling #Html.ValidateFor() for your properties. This creates HTML markup outside of the div created by #Html.ValidationSummary.
Because this markup is outside of where unobtrusive validation expects it, this markup is never overwritten, and will always remain. Remove the #Html.ValidateFor() lines. If you need to have the validation messages after your initial load, call validate() on document.ready to set your validation messages.

Because I haven't found a proper solution to this problem, I've decided to simply target the validation-summary-errors div and add the class display:none; to the li elements. This hides the validation errors that have otherwise not cleared before submitting the form.
$('#form_errors').children('div.validation-summary-errors').children('ul').children('li').css('display','none')
There has to be a better solution, but I've tried everything and can't figure out why my attempts to force validation don't work.

Related

Cant find page after POST redirect C#

I go to a View, submit data via POST, but the redirect cannot find the Controller method. What am I doing wrong here? After submitting the form I get:
404 error: cannot find page. URL is: http://localhost:52008/InternalController/UpdateCardFormPost
Snippet from InternalController.cs:
public ActionResult UpdateCardFormView()
{
var CardToUpdate = new CardView();
return View(CardToUpdate);//return implementation of Cards.cshtml with the empty model that was passed to it
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult UpdateCardFormPost(CardView c)
{
CardModelIO.WriteCard(c);//#TODO: IMPLEMENT
return View("CardDetailView", c);
}
UpdateCardFormView.cshtml (the view with the form I am submitting):
#using LeanKit.API.Client.Library.TransferObjects
#model CardView
<!DOCTYPE html>
<html>
<!--Form used to change a card
STARTING DISPLAY called by in Internal/UpdateCardFormView
ENDING DISPLAY (post) called by UpdateCardForm in InternalController a specified below-->
<head>
</head>
<body>
#Html.BeginForm("UpdateCardFormPost", "InternalController", FormMethod.Post)
#Html.TextBoxFor(c => c.AssignedUserName);
<input type="submit" value="Submit Changes" />
</body>
</html>
Heres the CardDetailView.cshtml (the view I should be redirected to):
#using LeanKit.API.Client.Library.TransferObjects
#model IEnumerable<CardView>
<!--used for displaying an individual card in detail view
referenced in UpdateCardFormPost() method of Internal controller-->
<!DOCTYPE html>
<html>
<head>
</head>
<body>
CardView j = Model;
<p>j.AssignedUserId</p>
</body>
</html>
You've specified the controller name as InternalController but it's probably just called "Internal".
Try changing
#Html.BeginForm("UpdateCardFormPost", "InternalController", FormMethod.Post)
to
#Html.BeginForm("UpdateCardFormPost", "Internal", FormMethod.Post)
you are missing closing form tag
you should do it like
using (#Html.BeginForm("UpdateCardFormPost", "InternalController", FormMethod.Post))
{
...
}
#using(Html.BeginForm())
{
#Html.TextBoxFor(c => c.AssignedUserName);
<input type="submit" value="Submit Changes" />
}

Error loading hubs. Ensure your hubs reference is correct, e.g. <script src='/signalr/js'></script>

There are two pages: Login.aspx and Profile.aspx, which are built using HTML and AngularJS.
The login.aspx page uses ng-view to get the template of Login-view or Signup View.
The code used is:
<head>
<title></title>
<base href="/Login.aspx" />
<link href="StyleSheet/Login_css.css" rel="stylesheet" />
<script src="JscriptVendors/angular.min.js"></script>
</head>
<body ng-app="JouralApp_login">
<div ng-view></div>
<script src="Jscript_Angular/Model.js"></script>
<script src="Jscript_Angular/Controllers/LoginPageController.js"></script>
<script src="JscriptVendors/angular-route.min.js"></script>
<script src="JscriptVendors/angular-animate.min.js"></script>
<script src="JscriptVendors/jquery.min.js"></script>
</body>
The views are stored in Template folder with the names as: loginTemplate.html, and signupTemplate.html.
The module used for handling the login.aspx page is:
var app_login = angular.module('JouralApp_login', ['ngRoute','ngAnimate']);
var app_profile = angular.module('GameApp', []);
app_login.config(['$routeProvider', '$locationProvider', function ($routeProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$routeProvider
.when('/login', {
templateUrl: 'Jscript_Angular/Templates/loginTemplate.html',
controller: 'loginController'
})
.when('/signup', {
templateUrl: 'Jscript_Angular/Templates/signupTemplate.html'
}).otherwise({
redirectTo:'/login'
})
}]);
Now a created my Profile.aspx, with the HTML code as:
<head>
<script src="Scripts/angular.js"></script>
</head>
<body ng-app="app_profile">
<div ng-controller="chatController">
<div>
<div ng-repeat="chat in messages">{{chat}}</div>
<div>
<input type="text ng-model="message" />
<input type="button" ng-click="newMessage()" />
</div>
</div>
</div>
<script src="Jscript_Angular/Model.js"></script>
<script src="Scripts/jquery-1.6.4.js"></script>
<script src="Scripts/jquery.signalR-2.2.0.js"></script>
<script src="signalr/hub"></script>
<script src="Jscript_Angular/Controllers/ChatController.js"></script>
</body>
Every thing was working fine until I try to integrate SignalR into my project.
I made two classes:
CLASS 1:
[assembly: OwinStartup(typeof(Startup))]
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.MapSignalR();
}
}
CLASS 2:
public class ChatHub : Hub
{
public void SendMessage(string name, string message)
{
Clients.All.broadcastMessage(name, message);
}
}
I also made the following controller in order to access my javascript function:
app_profile.controller('chatController',['$scope', function ($scope) {
$scope.name = 'Guest';
$scope.message = '';
$scope.messages = [];
$scope.chatHub = null;
$scope.chatHub = $.connection.chatHub;
$.connection.hub.start();
$scope.chatHub.client.broadcastMessage = function (name, message) {
var newMessage = name + " " + message;
$scope.messages.push(newMessage);
$scope.$apply();
};
$scope.newMessage = function () {
$scope.chatHub.server.sendMessage($scope.name, $scope.message);
$scope.message = '';
}
}]);
Now when I try to access my profile page, it show the error
angular.js:13550 Error: SignalR: Error loading hubs. Ensure your hubs reference is correct, e.g. .
Also when i try to access, localhost:5136/signalr/hubs, it redirects me to my login page, i.e: localhost:5136/login
I think the problem is that, it cannot access the hub which I created because of the routing which i did using angularJS for the login page.
Please help me find the solution.

AngularJS Controller not defined

So I've been browsing other threads, however none of the fixes I've found have solved my issue. I hope some of the more experienced coders here will be kind enough to help me out, mods I'm sorry if it turns out I'm being stupid here.
So I've built an app in Angular for an asp.net web app, the angular module should be displaying data from an entity model and displaying it inside a div.
Right now the code is not working, and I have no errors. From what I've seen I suspect its the Booking-controller however I cannot fathom what's wrong.
Here's my code
_Layout.cshtml
` <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>#ViewBag.Title - Web App</title>
#Styles.Render("~/Content/css")
#Styles.Render("~/Content/js")
#Scripts.Render("~/bundles/angular")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/bootstrap")
</head>
<body ng-app="BookingsApp">
//a bunch of navbar stuff and other content
#RenderSection("scripts", required: false)
</body>
</html>
`
HomeController.cs
`using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
namespace WebApp.Controllers
{
public class HomeController : Controller
{
//More navigation stuff
public JsonResult GetAll()
{
List<Booking_form> Booking = new List<Booking_form>();
using (BookingEntities1 ed = new BookingEntities1())
{
Booking = ed.Booking_forms.ToList();
return new JsonResult { Data = Booking, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
}
}
}
Page where I expect booking to be displayed
#section scripts{
<script src="~/Content/Angular/BookingModule.js"></script>
<script src="~/Content/Angular/BookingController.js"></script>
<script src="~/Content/Angular/BookingService.js"></script>
<link href="~/Content/TableStyle.css" rel="stylesheet" />
}
<div ng-controller="BookingController">
<table>
<tr>
<th>Id</th>
<th>Class</th>
<th>Day</th>
</tr>
<tr></tr>
<tr ng-repeat="e in BookingList">
<td>{{e.BookingId}}</td>
<td>{{e.ClassName}}</td>
<td>
{{e.Day}}
</td>
</tr>
</table>
</div>
Angular Module
var app = angular.module('BookingsApp',[]);
Angular Service
app.service('BookingService', function ($http) {
this.getBookings=function () {
return $http.get('/HomeController/GetAll');
}
});
Angular Controller
`app.controller('BookingController',function($scope,BookingService) {
function getBookingList() {
BookingService.getBookings().then(function (emp) {
$scope.BookingList = emp.data;
}, function (error) {
alert('Failed to fetch data');
});
}
});
`
I'd prefer to have a div on the page displaying the info with the ng-app="BookingApp" line, however this caused the BookingController reference to cause errors.
Any help would be greatly appreciated.
Edit:
Having looked again through browser console this message appears for all 3 angular scripts:
`Resource interpreted as Stylesheet but transferred with MIME type application/javascript: "http://localhost:49532/Content/Angular/BookingModule.js".
Solved, had to do a complete rebuild and make use of the service factory. For anyone else encountering this issue, see the provided link for a tutorial.
http://www.infragistics.com/community/blogs/dhananjay_kumar/archive/2015/05/13/how-to-use-angularjs-in-asp-net-mvc-and-entity-framework-4.aspx
note this solution will not work if solution uses multiple tables with foreign key dependencies.

From as partial view in layout page. MVC 5

I have a Partial View in my Layout page which contain a Form. The partial view open as popup. After submitting form I have to return back to the current page with opened popup and a success message should appear there but I am not able to return back to the right view.
My Layout Page
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>#ViewBag.Title || Midas WebSite</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryui")
#Scripts.Render("~/bundles/site")
#Scripts.Render("~/bundles/modernizr")
<script type="text/javascript" language="javascript">
/* Superior Web Systems */
function displayHideBox(boxNumber) {
if (document.getElementById("LightBox" + boxNumber).style.display == "none") {
$("#LightBox" + boxNumber).fadeIn();
$("#grayBG").fadeIn();
} else {
$("#LightBox" + boxNumber).fadeOut();
$("#grayBG").fadeOut();
}
}
</script>
</head>
<body>
<div id="grayBG" class="grayBox" style="display:none;"></div>
<div id="LightBox1" class="box_content" style="display:none;">
<div onclick="displayHideBox('1'); return false;" class="close">X</div>
#Html.Action("ActionToBindPartialView", "ControllerName")
</div>
#RenderBody()
#RenderSection("scripts", required: false)
#Scripts.Render("~/bundles/jqueryval")
My Partial View
<div id="divActions">
// My Form Here
#Ajax.ActionLink("Submit", "ActionName", "ControllerName", new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "divActions",
OnSuccess = "onSucess()"
})
</div>
Now my action code which I have tried so far:
1.
// My Code
return PartialView("MyPartialView");
2
// My Code
return PartialView("MyPartialView", MyModel);
3
// My Code
return View();
4
// My Code
return ParialView();
I am a beginner and not able to find what I am doing wrong. Please suggest what should I do to make this work.
It is hard to say what you are doing wrong, due to the limited workspace that we have to discuss the problem. However here is a working example that may help you, please follow each step:
Bundles
bundles.Add(new ScriptBundle("~/bundles/jquery")
.Include("~/Scripts/jquery-{version}.js"));
bundles.Add(new ScriptBundle("~/bundles/jqueryval")
.Include(
"~/Scripts/jquery.unobtrusive*",
"~/Scripts/jquery.validate*"));
HomeController
public ActionResult Index()
{
return View();
}
public PartialViewResult GetPartial()
{
return PartialView("_MyPartial");
}
Index.cshtml
<h2>Index</h2>
<div id="divActions">
#Ajax.ActionLink("Submit", "GetPartial", "Home", new AjaxOptions
{
HttpMethod = "POST",
UpdateTargetId = "divActions",
OnSuccess="onSuccess()"
})
</div>
<script type="text/javascript">
function onSuccess()
{
alert("Success!");
}
</script>
_MyPartial.cshtml
<h2>_MyPartial</h2>
_Layout.cshtml
<!DOCTYPE html>
<html>
<head>
<title>#ViewBag.Title</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
</head>
<body>
#RenderBody()
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
#RenderSection("scripts", required: false)
</body>
</html>
To confirm the rendered scripts in the page source (in the browser):
<script src="/Scripts/jquery-1.8.2.js"></script>
<script src="/Scripts/jquery.unobtrusive-ajax.js"></script>
<script src="/Scripts/jquery.validate.js"></script>
<script src="/Scripts/jquery.validate.unobtrusive.js"></script>
As you can see, there is nothing hard about it. You just need to follow the steps above.
I hope it helps.
Hint: check for other scripts errors, maybe your custom code to show the popup is causing a error. Double check if you are rendering javascript inside the partial view. Consider extract it to the regular view.

Request.Files[""] Keep returning null

Using uploadify to auto submit a users files, in my controller method Request.Files["Name"] keeps returning null but request.form isn't null, I can see the file in request.form when I set a breakpoint and debug it. Am I missing something? I'm testing this on mvc2 but i plan on using it on mvc4.
<link href="../../Content/uploadify.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://code.jquery.com/jquery-1.7.2.min.js"></script>
<script src="../../Scripts/jquery.uploadify.js" type="text/javascript"></script>
<script type="text/javascript">
$(function () {
$('#file_upload').uploadify({
'swf': '/Content/uploadify.swf',
'uploader': '/Home/UploadFile',
'auto': true
// Your options here
});
});
</script>
</head>
<body>
<%--<% using (Html.BeginForm("UploadFile", "Home", FormMethod.Post,
new { enctype = "multipart/form-data" }))
{ %>--%>
<input type="file" name="file_upload" id="file_upload" style="margin-bottom: 0px" />
<%-- <% } %>--%>
Controller Method:
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase file)
{
var theFile = Request.Files["file_upload"];
return Json("Success", JsonRequestBehavior.AllowGet);
}
If I add a submit button and then submit it it will work though. I need to be auto though without a submit button.
IIRC Uploadify uses fileData as parameter. So:
var theFile = Request.Files["fileData"];
or even better:
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase fileData)
{
// The fileData parameter should normally contain the uploaded file
// so you don't need to be looking for it in Request.Files
return Json("Success", JsonRequestBehavior.AllowGet);
}
Of course if you are not happy with this name you could always customize it using the fileObjName setting.

Categories

Resources