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" />
}
Related
I have a partial view which renders a visual form made entirely in HTML with some .css. What I want to do is reuse this same form in the same page [n] number of times. In my HomeController class I am instantiating the model as such:
public IActionResult Index()
{
List<Foo> foos = new List<Foo>();
foos.Add(new Foo { Name = "John" });
foos.Add(new Foo { Name = "Dave" });
foos.Add(new Foo { Name = "Sean" });
foos.Add(new Foo { Name = "Alan" });
return View(foos);
}
Then in my index.cshtml I am iterating using the list I receive from my controller and generating a partial view based on the length of my list
#model List<HelloWorld.Models.Foo>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Foo</title>
<link rel="stylesheet" href="~/foo/styles.css" />
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<script src="~/foo/FooActions.js"></script>
</head>
<body>
#{
foreach (Foo foo in Model)
{
ViewData["Name"] = foo.Name;
<partial name="_Foo" view-data="ViewData" />
}
}
</body>
</html>
This is how I have my partial view set up:
<script type="text/javascript">
init('#ViewBag.Name');
</script>
<div class="foo-background">
<section>
<div>
<span class="score-text" id="redText">0</span>
</div>
<div class="green-bar"></div>
<div class="red-bar"></div>
<div>
<span class="bonus-score-text" id="greenText">0</span>
</div>
</section>
<section>
<div class="alphanumeric-display">
<p class="alphanumeric-display-text" id="textLine1">Text</p>
<p class="alphanumeric-display-text" id="textLine2">Text</p>
<p class="alphanumeric-display-text" id="textLine3">Text</p>
</div>
<div>
<span class="person-grade-text" id="goldText">0</span>
</div>
</section>
</div>
This form pulls data from a local database and displays data based on the person its tied to. The data shows up fine if its only displaying data of one person in the page. I'm using JavaScript to grab either the class or the id of these html elements and update their respective data.
But now what its doing is showing all the forms side-by-side, only, the data is wrong. None of the forms show the data from the table as they appear in the database. Upon closer inspection looks like it has a problem where each of these forms cant have the same class or ids. I'm getting this in error in all places where I have class or id elements
id attribute value must be unique: Document has multiple static
elements with the same id attribute: textLine1
Its the same error for each of my html elements.
Can someone help me understand what I am doing wrong? What can I do in order to get this to work properly?
I have some problem with my ASP.NET MVC application. How can I modify an existing object created previously in different ActionResult?
I created object in this action:
public ActionResult getLogin(AccountViewModel accountViewModel)
{
Account account2 = de.Accounts.FirstOrDefault(a => a.Username == accountViewModel.Account.Username);
PasswordReminder.PasswordReminder reminder = new PasswordReminder.PasswordReminder();
reminder.showQuestion(account2.Username);
return View("Question", reminder);
}
And I want to add an attribute to the existing reminder object by this ActionResult
#model PasswordReminder.PasswordReminder
#{
Layout = null;
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Question</title>
</head>
<body>
<div>
#Model.questionReminder
#using (Html.BeginForm("Answer", "Account", FormMethod.Post))
{
#Html.TextBoxFor(a => a.reminderAnswer)
<input type="submit" value="Send" />
}
</div>
</body>
</html>
So in my View "Answer" in attribute "reminderAnswer" I entered value but questionReminder is null, so this must be a new object.. Thanks for all help
If I have understood your question correctly, in order to achieve what you are after, the PasswordReminder object that you are using as your Model, must be persisted in the getLogin action, and then passed back separately as the model from your action that feeds your Answer view (but I recommend to use a ViewModel as an abstraction over the previous PasswordReminder object for security)
This would insure you are referencing the previously instantiated PasswordReminder object in your Answer view, in order to modify the value of reminderAnswer property.
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.
I've got a user login page that I want to check if the inserted credentials are correct. Here's the controller:
EDITED:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using SustIMS.Models;
namespace SustIMS.Controllers
{
public class MainController : Controller
{
public static string userName;
public static string password;
public ActionResult Index()
{
getCredentials();
if (Authenticate(userName, password))
{
return View();
}
ModelState.AddModelError("", "Could not authenticate");
return Redirect("../Home");
}
public void getCredentials()
{
if (Request["username"] != null && Request["password"] != null)
{
userName = Request["username"].ToString();
password = Request["password"].ToString();
}
}
}
}
Everything is OK if the inserted credentials are correct: the Authenticate function verifies that and if it returns true, the ActionResult returns the View.
However, if they are not correct, I set it to return null, going to a blank page instead.
I want it to stay on the same page and display some kind of message to the user informing that the credentials aren't correct (by showing a div, calling a javascript function with a popup window, ..., I don't really know).
How can I do that?
Thanks
EDIT
Here's my view:
#{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>#ViewBag.Message</title>
#Styles.Render("~/Content/css")
#Scripts.Render("~/bundles/modernizr")
#Scripts.Render("~/bundles/jquery")
</head>
<body>
<div id="outer-limit">
<div class="logo-main">
<a href="../Home/Index">
<img class="displayed" src="../../Images/logo.png" alt="SustIMS" /></a>
</div>
<section class="container">
#Html.Partial("LoginForm")
#Html.ValidationSummary()
</section>
</div>
</body>
</html>
And the partial LoginForm:
<div class="login">
<h1>#ViewBag.Login</h1>
<form method="get" action="../Main/Index">
<p>
<input type="text" name="username" value="" placeholder="Username" maxlength="30"></p>
<p>
<input type="password" name="password" value="" placeholder="Password" maxlength="25"></p>
<br />
<br />
<p class="submit">
<input type="submit" onclick="Refresh()" name="commit" value="Login"></p>
</form>
</div>
doing something like this should work. Checking the ModelState can/will validate required fields via Attributes on your view (if you've implemented them) otherwise you can manually take care of that in your action. Adding the model error before returning the view will cause the error to display on the page after it reloads. Upon successful authentication, we're redirecting to another Action.
public ActionResult Index(LoginModel model) {
if (ModelState.IsValid) {
if (AuthenticateUser(model)) {
return RedirectToAction("LoggedIn");
} else {
ModelState.AddModelError("", "Could not authenticate"); //or better error
}
}
return View(model);
}
be sure to also add an #Html.ValidationSummary() to your view to display the error message returned.
You should be able to tailor the above code to work with your methods, but ultimately, I would recommend strongly typing your views and passing a model back through a post.
EDIT
Redid my example based on your code above, rather than a general example
public ActionResult Index()
{
getCredentials();
if (Authenticate(userName, password))
{
return View();
}
ModelState.AddModelError("", "Could not authenticate");
return View();
}
My recommendation would be to RedirectToAction after successful authentication, rather than returning the same view.
One way to do that :
public ActionResult Index(string url)
{
getCredentials();
if (Authenticate(userName, password))
{
return View();
}
else
{
TempData["ErrorMessage"]="Wrong Credential";
return Redirect(url);
}
}
}
Then in your view Show the message in a div if it's not empty
#if(TempData["ErrorMessage"] != null)
{
<div class='alert alert-success alert-dismissable' >
#TempData["ErrorMessage"]
</div>
}
I believe you have wrong idea how ASP.NET MVC works. If you submit form, the whole new request is made, and its response will be shown - that is, you must return something to display back yo user - typically view. Never return as ActionResult. In your case, you return View() in both cases, just give it different data to display - succeess message or error message for example. You can use strongle typed model for this, or ViewBag - take a look at some tutorials.
If you want user to "stay on the same page" if credentials are wrong, you need some kind of ajax validation. ASP.NET MVC supports this also, take a look at http://msdn.microsoft.com/en-us/library/gg508808(vs.98).aspx
I believe I'm missing something quite trivial here, but I'm not spotting it. I have a Post method, which modifies a Model property. I then want that model property to reflect the new property value. So here are the pieces:
Controller:
[HttpPost]
public ActionResult Index(HomeModel model)
{
ModelState.Clear(); //Didn't help
model.MyValue = "Hello this is a different value";
return View(model);
}
Model:
public class HomeModel
{
[Display(Name = "My Message")]
public string MyValue { get; set; }
}
View:
#model MyApp.Models.HomeModel
#{
ViewBag.Title = "My MVC App";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title></title>
</head>
<body>
<div>
#using (Html.BeginForm("Index", "Home"))
{
<h5>Hello</h5>
<input id="SendMessage" type="submit" value="Send Message"/>
#Html.LabelFor(m => m.MyValue)
}
</div>
</body>
</html>
When I debug the controller I can see the updated model, but my LabelFor always has the Display attribute as opposed to the value I provided of "Hello this is a different value". What am I missing here that this label is not updated?
#Html.LabelFor displays your property name (or the name defined in your DisplayAttribute), whereas #Html.DisplayFor displays your property content. If your want "Hello this is a different value" displays, replace #Html.LabelFor by #Html.DisplayFor
The html helper look at the ModelState when binding their values and then in the model.
So if you intend to modify any of the POSTed values inside your controller action make sure you remove them from the model state first:
ModelState.Remove("PropertyName");
Read this MVC 3 - Html.EditorFor seems to cache old values after $.ajax call
That's the purpose of LabelFor, display the property name. Either use EditorFor or just access the model property directly inside a label tag it to your view
<h5>Hello</h5>
<input id="SendMessage" type="submit" value="Send Message"/>
<label>#Model.MyValue</label>