Load ASP-MVC View with Ext.Panel loader - asp.net-mvc

I have following layout, related to the one i am describing in this question
<ext:Viewport runat="server">
<Items>
<ext:Panel Region="North" runat="server" ID="TopBar" />
<ext:Panel Region="West" runat="server" ID="Nav" >
<Items>
<ext:Button runat="server" ID="loaderComponentFooBar">
<DirectEvents>
<Click OnEvent="loadFooBar" />
</DirectEvents>
</ext:Button>
//Some more Buttons each with his own loader Function in Code-Behind
</Items>
</ext:Panel>
<ext:Panel runat="server" Region="center" ID="MainPanel" />
</Items>
</ext:Viewport>
on Button-Click i now want to load my View # "/Foo/Bar/" to the MainPanel
How can i achieve this in CodeBehind?
I already tried:
public void loadFooBar(object sender, DirectEventArgs e)
{
MainPanel.Loader.Url = "/Foo/Bar/"; //Throws null reference Exception
MainPanel.Loader.Url = "~/Foo/Bar/"; // same as above
MainPanel.Loader.GetUrlByRoute("Foo/Bar/"); //again the same
MainPanel.Loader.LoadContent("/Foo/Bar/");
//and after each of these attempts except the last went:
MainPanel.Loader.Mode = LoadMode.Frame;
MainPanel.Loader.LoadMask.ShowMask = false;
MainPanel.Loader.LoadContent();
}
Just by the way, i am using aspx-web-application views

I think you should not use a page's code behind for DirectEvents' handlers. It is going out of the MVC concept. You should refer a controller's actions.
Here is an example.
Example View
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<%# Register Assembly="Ext.Net" Namespace="Ext.Net" TagPrefix="ext" %>
<!DOCTYPE html>
<html>
<head runat="server">
<title>Ext.Net.MVC v2 Example</title>
</head>
<body>
<ext:ResourceManager runat="server" />
<ext:Viewport runat="server" Layout="BorderLayout">
<Items>
<ext:Panel runat="server" Region="West" Width="100">
<Items>
<ext:Button
runat="server"
Text="Load View 1"
DirectClickUrl=<%# Url.Action("LoadView1") %>
AutoDataBind="true" />
<ext:Button
runat="server"
Text="Load View 2"
DirectClickUrl=<%#Url.Action("LoadView2") %>
AutoDataBind="true" />
</Items>
</ext:Panel>
<ext:Panel ID="MainPanel" runat="server" Region="Center">
<Loader runat="server" Mode="Frame" AutoLoad="false">
<LoadMask ShowMask="true" />
</Loader>
</ext:Panel>
</Items>
</ext:Viewport>
</body>
</html>
Example Controller
using System.Web.Mvc;
using Ext.Net;
using Ext.Net.MVC;
namespace Work2MVC.Controllers
{
public class AspxController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult View1()
{
return View();
}
public ActionResult View2()
{
return View();
}
public ActionResult LoadView1()
{
Panel p = X.GetCmp<Panel>("MainPanel");
p.LoadContent(Url.Action("View1"));
return this.Direct();
}
public ActionResult LoadView2()
{
Panel p = X.GetCmp<Panel>("MainPanel");
p.LoadContent(Url.Action("View2"));
return this.Direct();
}
}
}
Also you can initiate a load request on client side via JavaScript. Then you avoid an additional request.

Related

Avoid a loop in index page

I have this index.jsp:
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%# taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
</head>
<body>
<h2>Simple Iterator</h2>
<ol>
<s:iterator value="comboMeals">
<li><s:property /></li>
</s:iterator>
</ol>
<h2>Iterator with IteratorStatus</h2>
<table>
<s:iterator value="comboMeals" status="comboMealsStatus">
<tr>
<s:if test="#comboMealsStatus.even == true">
<td style="background: #CCCCCC"><s:property/></td>
</s:if>
<s:elseif test="#comboMealsStatus.first == true">
<td><s:property/> (This is first value) </td>
</s:elseif>
<s:else>
<td><s:property/></td>
</s:else>
</tr>
</s:iterator>
</table>
</body>
</html>
This is my Java Class:
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
public class IteratorKFCAction extends ActionSupport{
private List<String> comboMeals;
public List<String> getComboMeals() {
return comboMeals;
}
public void setComboMeals(List<String> comboMeals) {
this.comboMeals = comboMeals;
}
public String execute() {
comboMeals = new ArrayList<String>();
comboMeals.add("Snack Plate");
comboMeals.add("Dinner Plate");
comboMeals.add("Colonel Chicken Rice Combo");
comboMeals.add("Colonel Burger");
comboMeals.add("O.R. Fillet Burger");
comboMeals.add("Zinger Burger");
return SUCCESS;
}
}
My idea was call directly the action that fill the index page, so i put this line inside head tags of index.jsp
<META HTTP-EQUIV="Refresh" CONTENT="0;URL='start.do'">
But with with this fix, i get that the page enter in a "refresh loop". Is there any way to call directly from the code the action, in this way I don't have to set it manually via URL in the browser.
I've tried also a second solution adding to the body of index.jsp this code:
<s:action name="iteratorKFCAction" executeResult="true" />
where iteratorKFCAction is the action specified in struts.xml that recall the IteratorKFCAction. In this case the action loop.
The main purpose of Struts2 (and all other MVC frameworks) is to route the URL to an Action (the Controller) that prepare data (in your case comboMeals) and determine a result (in your case always SUCCESS) that is mapped to a template (the View), in your case index.jsp
In your struts.xml you should have something like
<action name="start.do" class="com.xxx.IteratorKFCAction">
<result name="SUCCESS">/WEB-INF/.../index.jsp</result>
</action>

MVC4 RedirectToAction returns HTTP 404

My RedirectToAction returns HTTP 404, except the controller, action and view are there, spelled correctly with proper caps. I am in SubscriberController and I want to call an action in CreateTestController.
Here is my initial url:
http://www.localdomain.com/Subscriber/AuthUser
This launches the page which has several forms in it, the one I'm using for this call is below:
<form id="btnform7" action="LaunchTestPortal" method="post">
<input name="__RequestVerificationToken" id="antiforge7" type="hidden" value="rzTdAi...aj501">
<button title="Create, Edit or Review Training" class="ui...active" id="btnLaunchTestPortal" role="button" style="width: 13em; height: 22px; margin-bottom: 10px;" type="submit">
<span class="ui-text-only">Create, Edit or Review Training</span>
</button>
</form>
this successfully calls this method in the SubscriberController
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LaunchTestPortal()
{
return RedirectToAction("CreateTestPortal", "CreateTest");
}
This is the method I want to call in CreateTestController
[HttpPost]
[ValidateAntiForgeryToken]
public ViewResult CreateTestPortal()
{
...
}
after the call, this is the address it returns http://www.localdomain.com/CreateTest/CreateTestPortal
except the page result is HTTP 404 not found.
All the parts are there. It just the redirect in controllerA won't call the method in controllerB
I put comments in the for my changes, so that you can learn.
public class SubscriberController : Controller
{
//
// GET: /Subscriber/
public ActionResult AuthUser()
{
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult LaunchTestPortal()
{
return RedirectToAction("CreateTestPortal", "CreateTest");
}
}
public class CreateTestController : Controller
{
//removed two attributes
public ViewResult CreateTestPortal()
{
var ap = "dh";
return View();
}
}
AuthUser.cshtml
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>AuthUser</title>
</head>
<body>
#*added Subscriber below*#
<form id="btnform7" action="/Subscriber/LaunchTestPortal" method="post">
#*changing next line*#
#Html.AntiForgeryToken()
#*<input name="__RequestVerificationToken" id="antiforge7" type="hidden" value="rzTdAi...aj501">*#
<button title="Create, Edit or Review Training" class="ui...active" id="btnLaunchTestPortal" role="button" style="width: 13em; height: 22px; margin-bottom: 10px;" type="submit">
<span class="ui-text-only">Create, Edit or Review Training</span>
</button>
</form>
</body>
</html>
CreateTestPortal.cshtml
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>CreateTestPortal</title>
</head>
<body>
<div>
</div>
</body>
</html>

MVC4 model binding with two complex models

I have an action on my controller that takes two parameters that should be captured when a form is posted:
[HttpPost]
public ActionResult Index(MyModel model, FormAction action)
The idea is that the model data should be captured in MyModel and the button that the user pressed should be captured in FormAction:
public class MyModel
{
public string MyValue { get; set; }
}
public class FormAction
{
public string Command { get; set; }
}
Here is my view:
#model TestApp.Models.MyModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
#using (Html.BeginForm("Index", "Home"))
{
#Html.TextBoxFor(x => x.MyValue)
<input type="submit" value="OK" name="command" />
<input type="submit" value="Cancel" name="command" />
}
</div>
</body>
</html>
If I add another string parameter to the action called 'command' then the value of the button comes through but it doesn't get bound to the Command property on the FormAction parameter - the parameter is always null.
If I add a Command property to MyModel then the button value does come through.
Is there something in MVC model binding that prevents more than one complex model to be bound in one action method?
The metter is that Html.BeginForm sends only model from top statenent: #model TestApp.Models.MyModel. If I clearly understand what you whant to do, the better solution will be to create ViewModel:
public class ViewModel
{
public MyModel myModel {get; set;}
public FormAction formAction {get; set;}
}
Change View as follows:
#model TestApp.Models.ViewModel
#{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
</head>
<body>
<div>
#using (Html.BeginForm("Index", "Home"))
{
#Html.TextBoxFor(model=> model.myModel.MyValue)
#Html.TextBoxFor(model=> model.formAction.Command)
<input type="submit" value="OK" name="command" />
<input type="submit" value="Cancel" name="command" />
}
</div>
</body>
</html>
And change your Action to:
[HttpPost]
public ActionResult Index(ViewModel model)
I've got to the bottom of this and the reason it wasn't working was simply because the parameter was named action. This is pretty much the equivalent of a keyword in MVC and it is used by the MVC framework to identify the action to be executed.
Changing the parameter name to something else means that the Command property comes through as expected!

MVC 4 Updating a view with a controller action

I'm new to MVC. I want to be able to change a button/divs/textboxes text when a view's button is clicked. I found a tutorial online that showed me the following but when I click the button I'm getting redirected to another page. That page shows the text instead. I haven't touched the default Global.aspx
View
#using (Ajax.BeginForm("ExamineTextBox", new AjaxOptions { UpdateTargetId = "result" }))
{
#Html.TextBox("textBox1")
<input type="submit" value="Button" />
<span id="result" />
}
Controller
public string ExamineTextBox(string textBox1)
{
if (textBox1 != "Initial Data")
{
return "This text is MVC different from before!";
}
return String.Empty;
}
Make sure you have included the jquery.unobtrusive-ajax.js script to your page.
If you are using the default bundles (take a look at ~/App_Start/BundleConfig.cs - you will see a jqueryval bundle defined which combines and minifies all ~/Scripts/jquery.unobtrusive* and "~/Scripts/jquery.validate*" files):
#Scripts.Render("~/bundles/jqueryval")
and if not using bundles you could include only this script individually:
<script type="text/javascript" src="~/scripts/jquery.unobtrusive-ajax.js"></script>
It is this script that is required for Ajax.* helpers to work. As it name indicates it unobtrusively AJAXifies them. It depends on jQuery so make sure you have that one included as well.
Side note: In ASP.NET controller actions should return ActionResults, not strings:
public ActionResult ExamineTextBox(string textBox1)
{
if (textBox1 != "Initial Data")
{
return Content("This text is MVC different from before!");
}
return Content(String.Empty);
}
Here's how your full view code might look:
#{
Layout = null;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
<link href="~/favicon.ico" rel="shortcut icon" type="image/x-icon" />
<meta name="viewport" content="width=device-width" />
</head>
<body>
#using (Ajax.BeginForm("ExamineTextBox", new AjaxOptions { UpdateTargetId = "result" }))
{
#Html.TextBox("textBox1", "Initial Data")
<input type="submit" value="Button" />
<span id="result" />
}
#Scripts.Render("~/bundles/jquery")
#Scripts.Render("~/bundles/jqueryval")
</body>
</html>
and the controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
public ActionResult ExamineTextBox(string textBox1)
{
if (textBox1 != "Initial Data")
{
return Content("This text is MVC different from before!");
}
return Content(String.Empty);
}
}

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.

Resources