mvc-System.Web.Mvc.ViewUserControl - asp.net-mvc-2

Hey...
How can I send submit buttons'id from ViewUserControl to controler on post action? When I had normal view I could write something like this:
[HttpPost]
public ActionResult KontaktIzabran(string myId)
{
//some code
}
Now myId is alwasy null....
Here is my UserControl
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<KontaktModel>" %>
<%# OutputCache Duration="1200" VaryByParam="*" %>
<div id="sign-in-pop" class="popup">
<div class="modal fat-form">
<div class="clipper">
<div class="left"></div>
<div class="content">Sign In</div>
<div class="right"></div>
</div>
<% Html.BeginForm("IzborKontaktaPopUp", "Kontakt"); %>
<%: Html.ValidationSummary(true) %>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Naziv)%>
<%: Html.ValidationMessageFor(model => model.Naziv) %>
<input type="submit" value="Traži" name="submitButton" id="submitButton" />
<input type="submit" value="Dodaj novi" name="noviKontakt" />
</div>
<% Html.EndForm(); %>
</div>
</div>

[HttpPost]
public ActionResult KontaktIzabran(string myId, string noviKontakt)
{
if (!string.IsNullOrEmpty(noviKontakt))
{
// <input type="submit" value="Dodaj novi" name="noviKontakt" />
// was used to submit the form
}
else
{
// <input type="submit" value="Traži" name="submitButton" id="submitButton" />
// was used to submit the form
}
...
}

Well it looks like you don't have a form field called "myId", so the submit can't send that back to the controller. Instead it will send back a FormCollection containing the current values of these:
<%: Html.TextBoxFor(model => model.Naziv)%>
<input type="submit" value="Traži" name="submitButton" id="submitButton" />
<input type="submit" value="Dodaj novi" name="noviKontakt" />

Related

asp.net-mvc2 - Strongly typed helpers not using Model?

When using strongly typed helpers in MVC2 the input field values aren't taken from the Model property when a post is made. Is this default behavior?
(strongly typed) view with strongly typed helpers:
<div class="editor-label">
<%: Html.LabelFor(model => model.Name) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Name) %>
<%: Html.ValidationMessageFor(model => model.Name) %>
</div>
<div class="editor-label">
<%: Html.LabelFor(model => model.Price) %>
</div>
<div class="editor-field">
<%: Html.TextBoxFor(model => model.Price) %>
<%: Html.ValidationMessageFor(model => model.Price) %>
</div>
Controller action for: /Product/Edit/5
public ActionResult Edit(int id)
{
var p = new Product();
p.Name = "product 1";
p.Price = "100";
return View(p);
}
Html output:
<div class="editor-label">
<label for="Name">Name</label>
</div>
<div class="editor-field">
<input id="Name" name="Name" type="text" value="product 1" />
</div>
<div class="editor-label">
<label for="Price">Price</label>
</div>
<div class="editor-field">
<input id="Price" name="Price" type="text" value="100" />
</div>
Controller action for: /Product/Edit/5
[HttpPost]
public ActionResult Edit(Product p)
{
p.Name = "prrrrrrd 2";
return View(p);
}
Html output after form post (below I would expect the value of the input with id="Name" to be "prrrrrrd 2. Where does the strongly typed helper get it's value from?):
<div class="editor-label">
<label for="Name">Name</label>
</div>
<div class="editor-field">
<input id="Name" name="Name" type="text" value="product 1" />
</div>
<div class="editor-label">
<label for="Price">Price</label>
</div>
<div class="editor-field">
<input id="Price" name="Price" type="text" value="100" />
</div>
When using strongly typed helpers in MVC2 the input field values
aren't taken from the Model property when a post is made. Is this
default behavior?
Yes, they are first taken from the ModelState and then from the Model. If you intend to perform some modifications on the model in your POST action you need to remove them from the ModelState first. For example:
[HttpPost]
public ActionResult Edit(Product p)
{
ModelState.Remove("Name");
p.Name = "prrrrrrd 2";
return View(p);
}

To get focus back after postback. ASP.Net MVC 2 Web application using multiple html forms

I am using ASP.NET MVC2 application in C#. I have two HTML forms on my content page.
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2><%: ViewData["Message"] %></h2>
<form id="form1">
<input id="text1" type="text" />
<input type="submit" value="submit" />
</form>
<form id="form2">
<input id="text2" type="text" />
<input type="submit" value="submit" />
</form>
</asp:Content>
What I want to do is to set the focus to Text Box after post back. After "form1" is submitted, "text1" should have focus and similarly after "form2" is submitted, "text2" should have the focus so that the user doesn't have to use mouse to put the focus back in text box and continue typing.
The following code works fine for a single HTML form on the page.
<html>
<head>
<script>
void function setfocus() {
document.getElementById("text1").focus();
}
</script>
</head>
<body onload="setfocus();">
<form method="post" action="">
<input type="submit" value="submit">
<input id="text1" type="text">
</form>
</body>
</html>
*The problem is I have two HTML forms on the page. Another issue is my web forms are on the content page of asp.net master page which reside inside the and only master form has tag which has "onload" property.
A friend of mine suggested me to use Ajax's ScriptManager and UpdatePannel. However, the UpdatePannel doesn't like HTML's elements inside it. It seems only support asp.net control elements.
Very grateful for your guidance.
Try this
<%# Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2><%: ViewData["Message"] %></h2>
<form id="form1">
<input id="text1" type="text" />
<input name="selectedTextBox" type="hidden" value="text1" />
<input type="submit" value="submit" />
</form>
<form id="form2">
<input id="text2" type="text" />
<input name="selectedTextBox" type="hidden" value="text2" />
<input type="submit" value="submit" />
</form>
<script>
var textBoxID = "<%: Context.Request.Form["selectedTextBox"] %>";
void function setfocus() {
var textBox = document.getElementById(textBoxID);
if(textBox) textBox.focus();
}
</script>
Edit: Prefix Context to Request object
You could append a hash to the action attribute of the first form:
<form id="form1" action="#form1">
<input id="text1" type="text" />
<input type="submit" value="submit" />
</form>
<form id="form2">
<input id="text2" type="text" />
<input type="submit" value="submit" />
</form>
and then test for the presence of this hash in the url:
function setfocus() {
if (document.location.hash.indexOf('#form1') > -1) {
// form1 was submitted => set focus to the second textbox
document.getElementById("text2").focus();
} else {
document.getElementById("text1").focus();
}
}

ASP.NET MVC 2 - First submit button on site doesn't work - rest is fine!

Sorry for unclear title - I don't know how to describe that problem in one sentence. Code sample will make it clear.
First UP button do nothing when clicked. Rest works like it should!
Below my view:
<%# Page Title="" Language="C#"
MasterPageFile="~/Views/Shared/Main.Master"
Inherits="System.Web.Mvc.ViewPage<GeekClick.ViewModels.HomeViewModel>" %>
<asp:Content ID="Content2" ContentPlaceHolderID="head" runat="server">
<title>Beta</title>
</asp:Content>
<asp:Content ID="Content1" ContentPlaceHolderID="MainPageLinks" runat="server">
<h2>Najlepsze linki w sieci</h2>
<div id="HomePageLinks">
<%foreach (var link in Model.Links) { %>
<b><%:link.Description %></b><br />
<%: Html.ActionLink("details", "Index", "Link", new {id = link.LinkID}, null) %>
<% using (Html.BeginForm("UpVote", "Home", new { linkId = link.LinkID }, FormMethod.Post)) {%>
<input type="submit" value="UP" /> <% } %>
<%: link.Votes %>
<% using (Html.BeginForm("DownVote", "Home", new { linkId = link.LinkID }, FormMethod.Post)) {%>
<input type="submit" value="DOWN" /> <% } %>
<% } %>
</div>
</asp:Content>
Controller:
[HttpPost]
public RedirectToRouteResult UpVote(int linkId)
{
var updateLink = _geekDb.Link.Single(a => a.LinkID == linkId);
updateLink.Votes++;
_geekDb.SaveChanges();
return RedirectToAction("Index");
}
[HttpPost]
public RedirectToRouteResult DownVote(int linkId)
{
var updateLink = _geekDb.Link.Single(a => a.LinkID == linkId);
updateLink.Votes--;
_geekDb.SaveChanges();
return RedirectToAction("Index");
}
And finally generated html:
<!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 id="Head1">
<title>Beta</title>
<title>
</title></head>
<body>
<form method="post" action="./" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE1NDk5OTQxMTBkZLMRoMOmMkoaJsHIkFWLWjn7HFSzna1LBeMqvRiCxdDQ" />
</div>
<div id ="mainPage" >
<h2>title</h2>
<div id="HomePageLinks">
<b>Something </b><br />
details
<form action="/Home/UpVote?linkId=1" method="post">
<input type="submit" value="UP" /> </form>3
<form action="/Home/DownVote?linkId=1" method="post">
<input type="submit" value="DOWN" /> </form>
<b>Somedesc </b><br />
details
<form action="/Home/UpVote?linkId=2" method="post">
<input type="submit" value="UP" /> </form>10
<form action="/Home/DownVote?linkId=2" method="post">
<input type="submit" value="DOWN" /> </form>
</div>
</div>
</form>
</body>
</html>
There shouldn't be viewstate, should be?
I can't see there any problem in code. Someone can?
Looks like somewhere (perhaps in your Main.Master) you have a <form runat="server" /> that's messing things up.
It makes sense why your first button does not work - notice <form method="post" action="./"> at the top of your output - it's clashing with your other form and posting to the wrong action.

Model Binding with Ajax Form

i m using asp.net mvc2 and i m submitting a form through ajax using jquery. in this scenario model binding does not work
Here is my View code
<%using (Html.BeginForm("MeetingTodo", "OA", FormMethod.Post, new { id = "TaskForm" }))
{%><%=Html.Hidden("id",ViewContext.RouteData.Values["id"]) %>
<div class="container">
<%foreach (var val in Model.Distinct())
{ %>
<div class="grdrow" >
<div class="grdrightcaption" style="width:173px;" ><%=val.setupEmployee.EmployeeName%></div>
<div class="grdcells" ><%=Html.TextAreaFor(x => val.Todo, new { maxlength = 200, style="width:300px;" })%> <%=Html.HiddenFor(x => val.EmployeeID)%></div>
<div class="grdcells" style="width:50px;" ><%=Html.CheckBoxFor(x=>val.Required)%></div>
</div>
<%}%>
</div>
<br />
<button type="submit" class="button">save</button>
<%}%>
below is signature of my action method in the controller
public ActionResult MeetingTodo(IEnumerable<int> EmployeeID,IEnumerable<string> Todo, FormCollection collection, int id)
i find no values in EmployeeID and Todo variables when they are expected to contain list of values from the form. i will appreciate any help and suggestions
Edit one
<FORM id=TaskForm method=post action=/OA.mvc/MeetingTodo jQuery1286197019171="1"><DIV id=tablecontainer>
<DIV class=grdcaption>
<H2>Tasks</H2></DIV>
<DIV class=grdrow>
<DIV style="WIDTH: 173px" class=grdtopcaption>Participant</DIV>
<DIV style="WIDTH: 303px" class=grdtopcaption>Todo</DIV>
<DIV style="WIDTH: 50px" class=grdtopcaption>Required</DIV></DIV><INPUT id=id value=110 type=hidden name=id>
<DIV class=container>
<DIV class=grdrow>
<DIV style="WIDTH: 173px" class=grdrightcaption>Muhammad Adeel Zahid</DIV>
<DIV class=grdcells><TEXTAREA style="WIDTH: 300px" rows=2 cols=20 name=[0].Todo maxlength="200">Shahzad</TEXTAREA> <INPUT value=19 type=hidden name=[0].EmployeeID></DIV>
<DIV style="WIDTH: 50px" class=grdcells><INPUT value=true type=checkbox name=[0].Required><INPUT value=false type=hidden name=[0].Required></DIV></DIV>
<DIV class=grdrow>
<DIV style="WIDTH: 173px" class=grdrightcaption>Abdul Samad</DIV>
<DIV class=grdcells><TEXTAREA style="WIDTH: 300px" rows=2 cols=20 name=[1].Todo maxlength="200">Syed</TEXTAREA> <INPUT value=21 type=hidden name=[1].EmployeeID></DIV>
<DIV style="WIDTH: 50px" class=grdcells><INPUT value=true CHECKED type=checkbox name=[1].Required><INPUT value=false type=hidden name=[1].Required></DIV></DIV>
<DIV class=grdrow>
<DIV style="WIDTH: 173px" class=grdrightcaption>M. Kafayat Ullah</DIV>
<DIV class=grdcells><TEXTAREA style="WIDTH: 300px" rows=2 cols=20 name=[2].Todo maxlength="200"> Mansoor</TEXTAREA> <INPUT value=23 type=hidden name=[2].EmployeeID></DIV>
<DIV style="WIDTH: 50px" class=grdcells><INPUT value=true type=checkbox name=[2].Required><INPUT value=false type=hidden name=[2].Required></DIV></DIV>
<DIV class=grdrow>
<DIV style="WIDTH: 173px" class=grdrightcaption>Muhammad Shahzad</DIV>
<DIV class=grdcells><TEXTAREA style="WIDTH: 300px" rows=2 cols=20 name=[3].Todo maxlength="200"> Alioor</TEXTAREA> <INPUT value=26 type=hidden name=[3].EmployeeID></DIV>
<DIV style="WIDTH: 50px" class=grdcells><INPUT value=true type=checkbox name=[3].Required><INPUT value=false type=hidden name=[3].Required></DIV></DIV>
<DIV class=grdrow>
<DIV style="WIDTH: 173px" class=grdrightcaption>Syed Mansoor Ali</DIV>
<DIV class=grdcells><TEXTAREA style="WIDTH: 300px" rows=2 cols=20 name=[4].Todo maxlength="200"> Ali</TEXTAREA> <INPUT value=27 type=hidden name=[4].EmployeeID></DIV>
<DIV style="WIDTH: 50px" class=grdcells><INPUT value=true type=checkbox name=[4].Required><INPUT value=false type=hidden name=[4].Required></DIV></DIV></DIV><BR><BUTTON aria-disabled=false class="button ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only" role=button type=submit jQuery1286197019171="10"><SPAN class=ui-button-text>save</SPAN></BUTTON> </DIV></FORM>
and my method signature is like
public ActionResult MeetingTodo(IEnumerable<int> EmployeeID,IEnumerable<string> Todo, FormCollection collection, int id)
Is it possible to see what your view code look like?
It should look something like this:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<IEnumerable<Employee>>" %>
// Other code not in your example
<%using (Html.BeginForm("MeetingTodo", "OA", FormMethod.Post, new { id = "TaskForm" }))
{%>
<%=Html.Hidden("id",ViewContext.RouteData.Values["id"]) %>
<div class="container">
<% for (int i = 0; i < Model.Count(); ++i)
{ %>
<div class="grdrow" >
<div class="grdrightcaption" style="width:173px;" >
<%= Model[i].setupEmployee.EmployeeName%>
</div>
<div class="grdcells" >
<%= Html.TextAreaFor(x => x[i].Todo, new { maxlength = 200, style="width:300px;" })%> <%= Html.HiddenFor(x => x[i].EmployeeID)%>
</div>
<div class="grdcells" style="width:50px;" >
<%=Html.CheckBoxFor(x => x[i].Required) %>
</div>
</div>
<% }%>
</div>
<br />
<button type="submit" class="button">save</button>
<%}%>
// Other code not in your example
And your action method signature should look like this:
public ActionResult MeetingTodo(IEnumerable<Employee> Employees,
FormCollection collection,
int id)
I don't remember of the top of my head if you can set the type to IEnumerable<Employee> or if you have to set it to Employee[] in the action method signature, but one or the other should work.
Also note that on the first line you have to make sure you include the namespace in the Inherits attribute as such: System.Web.Mvc.ViewPage<IEnumerable<Namespace1.Namespace2.Namespace3.Employee>> and of course use whatever real name your employee class has.
Hope this helps.
I believe the reason you're not getting the correct values is because you're using Html.TextAreaFor the wrong way. The x in your code points to your Page.Model attribute while your val is not related to that attribute in a way that ASP.NET MVC2 can understand.
You could change your code to look something like this:
<%using (Html.BeginForm("MeetingTodo", "OA", FormMethod.Post, new { id = "TaskForm" }))
{%><%=Html.Hidden("id",ViewContext.RouteData.Values["id"]) %>
<div class="container">
var ix = 0;
<%foreach (var val in Model.Distinct())
{ %>
<div class="grdrow" >
<div class="grdrightcaption" style="width:173px;" ><%=val.setupEmployee.EmployeeName%></div>
<div class="grdcells" ><%=Html.TextArea(String.Format("employee[{0}].Todo", ix), val.Todo, new { maxlength = 200, style="width:300px;" })%>
<%=Html.Hidden(String.Format("employee[{0}].EmployeeID", ix), val.EmployeeID)%>
</div>
<div class="grdcells" style="width:50px;" >
<%=Html.CheckBox(String.Format("employee[{0}].Required", ix), val.Required)%>
</div>
</div>
<% ++ix
}%>
</div>
<br />
<button type="submit" class="button">save</button>
<%}%>
And then in your action declaration decorate your parameters as following:
public ActionResult MeetingTodo([Bind(Prefix = "employee")]Employee[] employees)
A better and cleaner way would be to do this though.
<% for (int i = 0; i < Model.Count(); ++i)
{ %>
<%= Html.HiddenFor(m => m[i].SomeAttribute) %>
<div><%= Html.TextAreaFor(m => m[i].SomeTextAttribute) %></div>
<% } %>

Why is the object passed to Delete action empty?

I've got a basic ASP.NET MVC 2 application. I've got adding and editing rows working just fine, but deleting won't work. The Delete view gets the correct record on the GET, but when posting back, the parameter that gets passed is empty, as in CategoryID = 0, all empty values. Because of that, no object is found to be deleted from the database and an exception is thrown. How can I get the correct Category to be passed to the HttpPost Delete action?
Here's what I've got in the controller:
public ActionResult Delete(int id)
{
return View(_categoryRespository.Get(id));
}
[HttpPost]
public ActionResult Delete(Category categoryToDelete)
{
try
{
_categoryRespository.Delete(categoryToDelete);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
This is the Delete view, which as I said correctly displays the data on the GET:
<%# Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MVCApp.Models.Category>" %>
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>Fields</legend>
<div class="display-label">CategoryID</div>
<div class="display-field"><%: Model.CategoryID %></div>
<div class="display-label">SectionName</div>
<div class="display-field"><%: Model.SectionName %></div>
<div class="display-label">CategoryName</div>
<div class="display-field"><%: Model.CategoryName %></div>
<div class="display-label">Content</div>
<div class="display-field"><%: Model.Content %></div>
</fieldset>
<% using (Html.BeginForm()) { %>
<p>
<input type="submit" value="Delete" /> |
<%: Html.ActionLink("Back to List", "Index") %>
</p>
<% } %>
Your form is not actually POSTing anything. You can add a hidden input with CategoryID, and then create a static Delete method in your repository that will accept CategoryID as a parameter (or instantiate a category by CategoryID and then call your existing Delete method).
Controller
public ActionResult Delete(int id)
{
return View(_categoryRespository.Get(id));
}
[HttpPost]
public ActionResult Delete(int categoryID)
{
try
{
_categoryRespository.Delete(categoryID);
return RedirectToAction("Index");
}
catch
{
return View();
}
}
View
<h2>Delete</h2>
<h3>Are you sure you want to delete this?</h3>
<fieldset>
<legend>Fields</legend>
<div class="display-label">CategoryID</div>
<div class="display-field"><%: Model.CategoryID %></div>
<div class="display-label">SectionName</div>
<div class="display-field"><%: Model.SectionName %></div>
<div class="display-label">CategoryName</div>
<div class="display-field"><%: Model.CategoryName %></div>
<div class="display-label">Content</div>
<div class="display-field"><%: Model.Content %></div>
</fieldset>
<% using (Html.BeginForm()) { %>
<p>
<input type="hidden" name="categoryID" value="<%: Model.CategoryID %>" />
<input type="submit" value="Delete" /> |
<%: Html.ActionLink("Back to List", "Index") %>
</p>
<% } %>