I'm by no means lazy, but already 2 days overdue on our current sprint in my first ever MVC project, so I've been using the Add View Wizard to generate strongly typed views, but now that I have started using ViewData classes as view models, the wizard generates fields for ViewDataBase, and not my derived ViewData.
I think that the derived ViewData is built by a factory at runtime, and assume that is why the designer/wizard can only give me the base class properties, but is there anything I can do about this?
ProfK,
Here is what I tried (VS 2010, MVC2):
public class ViewDataBase
{
public int ID { get; set; }
public string Name { get; set; }
}
public class CustomerViewData : ViewDataBase
{
public string Address { get; set; }
}
Right clicked on my Action and created a strongly typed Details view using CustomerViewData. The following gets generated:
<%# Page Language="C#" Inherits="System.Web.Mvc.ViewPage<MyApplication.Models.CustomerViewData>" %>
<!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>Index</title>
</head>
<body>
<fieldset>
<legend>Fields</legend>
<div class="display-label">Address</div>
<div class="display-field"><%: Model.Address %></div>
<div class="display-label">ID</div>
<div class="display-field"><%: Model.ID %></div>
<div class="display-label">Name</div>
<div class="display-field"><%: Model.Name %></div>
</fieldset>
<p>
<%: Html.ActionLink("Edit", "Edit", new { /* id=Model.PrimaryKey */ }) %> |
<%: Html.ActionLink("Back to List", "Index") %>
</p>
</body>
</html>
Related
how to set or get html elements inner text or html controls value in Razor syntax.
i know how we can do this in aspx file using Runat="server" attribute like this
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title><%Response.Write(Page.Title); %></title>
<script runat="server">
protected void Button1_ServerClick(object sender, EventArgs e)
{
p1.InnerText = "Hello " + textbox1.Value; //get textbox value and set in html p tag
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<input type="text" id="textbox1" runat="server" /><br />
<input type="button" id="btn" runat="server" value="Click Me" onserverclick="Button1_ServerClick" />
<p id="p1" runat="server">see result here</p>
</div>
</form>
</body>
</html>
Basically something like this...
View (SomeAction.cshtml):
...
<p>ViewBag.SomeValue</p>
...
Controller:
...
[HttpGet]
public ActionResult SomeAction()
{
ViewBag.SomeValue = "Hello";
return View();
}
...
However you should learn much about approach which is used to build applications using ASP.MVC. It's completely different than ASP.NET WebForms. WebForms technology uses events while ASP.MVC uses Model View Controller. You have to change your mindset.
A panel web control lets a developer put the panel on a page and define content that will appear inside the panel.
Is it possible to achieve similar functionality with a user control, where I define all my custom 'chrome' in the control, but am able to drop it on a page wherever I want and define the content inside on a per instance basis?
I think you are talking about a Templated User Control. Good luck!
Options:
1) Templated Controls as referred to by Uwe and Hanlet
2) jQuery UI library
3) ASP.NET 2.0 Web Parts
It's really tricky to implement no matter which way you go.
As Hanlet EscaƱo pointed out, this is complete possible to do. I'll show:
This is the user control markup:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="TemplatedUserControl.ascx.cs" Inherits="Templated_User_Control.TemplatedUserControl" %>
<table border="1">
<tr>
<th>Head</th>
</tr>
<tr>
<td>
<asp:PlaceHolder ID="plContent" runat="server"></asp:PlaceHolder>
</td>
</tr>
<tr>
<td>Foot</td>
</tr>
</table>
This is the user control code:
using System;
using System.Web.UI;
namespace Templated_User_Control
{
public partial class TemplatedUserControl : System.Web.UI.UserControl
{
private ITemplate content_m = null;
[TemplateContainer(typeof(ContentContainer))]
[PersistenceMode(PersistenceMode.InnerProperty)]
public ITemplate Content
{
get
{
return content_m;
}
set
{
content_m = value;
}
}
void Page_Init()
{
if (content_m != null)
{
ContentContainer container = new ContentContainer();
//This is the real magic. Take the contents, and put it in our ContentContainer object, then
//add the ContentContainer object as a child control of the placeholder so it renders inside the user control
content_m.InstantiateIn(container);
this.plContent.Controls.Add(container);
}
}
protected void Page_Load(object sender, EventArgs e) {}
public class ContentContainer : Control, INamingContainer {}
}
}
This is the page markup:
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Templated_User_Control.Default" %>
<%# Register src="TemplatedUserControl.ascx" tagname="TemplatedUserControl" tagprefix="uc1" %>
<!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></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<uc1:TemplatedUserControl ID="TemplatedUserControl1" runat="server">
<Content>
Template user control test.<br />
<asp:Literal ID="litTest" runat="server">this is a test!</asp:Literal><br />
abc 123!
</Content>
</uc1:TemplatedUserControl>
</div>
</form>
</body>
</html>
Yes, this is completely possible.
Here is a great example where a developer overrides an existing control (I chose an article with a Panel, since you used it as an example) and still allows content within.
The article is good, but you may find the sample code even more helpful.
I am new for Spring Framework. In my POC I am not getting the model value in jsp.
below is my code
My Controller is
#Controller
public final class ContactController {
#Autowired
private Validator validator;
public void setValidator(Validator validator) {
this.validator = validator;
}
#RequestMapping(value = "/form", method = RequestMethod.GET)
public String get(ModelMap model) {
// Because we're not specifying a logical view name, the
// DispatcherServlet's DefaultRequestToViewNameTranslator kicks in.
UserMessage Message = new UserMessage();
System.out.println("Hello Get Method");
model.addAttribute("userMessage", Message);
return "form";
}
#RequestMapping(value = "/form", method = RequestMethod.POST)
public String post(#ModelAttribute("userMessage") UserMessage userMsg,
BindingResult result, Model model) {
validator.validate(userMsg, result);
System.out.println(userMsg.getName());
model.addAttribute("userMsg",userMsg);
if (result.hasErrors()) { return "form"; }
// Use the redirect-after-post pattern to reduce double-submits.
return "thanks";
}
My jsp form is as below
<form:form modelAttribute="userMessage">
<div class="form-item">
<div class="form-label">Your name:</div>
<form:input path="name" size="40" cssErrorClass="form-error-field"/>
<div class="form-error-message"><form:errors path="name"/></div>
</div>
<div class="form-item">
<div class="form-label">Your e-mail address:</div>
<form:input path="email" size="40" cssErrorClass="form-error-field"/>
<div class="form-error-message"><form:errors path="email"/></div>
</div>
<div class="form-item">
<div class="form-label">Your message:</div>
<form:textarea path="text" rows="12" cols="60" cssErrorClass="form-error-field"/>
<div class="form-error-message"><form:errors path="text"/></div>
</div>
<div class="form-item">
<input type="submit" value="Submit" />
</div>
</form:form>
Configuration file as below
<bean id="configurationLoader"
class="org.springmodules.validation.bean.conf.loader.annotation.AnnotationBeanValidationConfigurationLoader"/>
<bean id="validator" class="org.springmodules.validation.bean.BeanValidator"
p:configurationLoader-ref="configurationLoader"/>
<!-- Load messages -->
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource"
p:basenames="errors"/>
<!-- Discover POJO #Components -->
<!-- These automatically register an AutowiredAnnotationBeanPostProcessor -->
<context:component-scan base-package="contact"/>
<!-- Map logical view names to physical views -->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp"/>
after filling the form I want the command Object details back in in jsp page so I write as below (thanks.jsp)
<%# page import="contact.UserMessage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Thank You</title>
</head>
<body>
<h1>Thank You</h1>
Welcome <%= request.getParameter("name") %>
Name is ${userMsg.name}
</body>
</html>
request.getParameter("name") is giving correct result but ${userMsg.name} is printing as it is why?
try to enable EL
<%# page isELIgnored="false" %>
Make sure that you have the taglib definition on the page:
%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
Given the following view model and action using the DefaultModelBinder, it seems to ignore the dictionary, but bind all other properties correctly. Am I missing something here? Looking at the MVC source code this seems legit.
Thanks
public class SomeViewModel
{
public SomeViewModel()
{
SomeDictionary = new Dictionary<string, object>();
}
public string SomeString { get; set; }
public IDictionary<string, object> SomeDictionary { get; set; }
}
[HttpPost]
public ActionResult MyAction(SomeViewModel someViewModel)
{
//someViewModel.SomeString binds correctly
//someViewModel.SomeDictionary is null
}
<%# Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<SomeViewModel>" MasterPageFile="~/Views/Shared/Site.Master" %>
<asp:Content runat="server" ID="Content2" ContentPlaceHolderID="MainContent">
<% using (Html.BeginForm("MyAction", "MyController")) {%>
<%= Html.EditorFor(m => m.SomeString) %>
<%= Html.EditorFor(m => m.SomeDictionary["somevalue"]) %>
<input type="submit" value="Go" />
<%} %>
</asp:Content>
And for reference, the HTML output is:
<input class="text-box single-line" id="SomeString" name="SomeString" type="text" value="" />
<input class="text-box single-line" id="Somedictionary_somevalue_" name="SomeDictionary[somevalue]" type="text" value="" />
EDIT: The above will not work as pointed out below, however I prefer this layout and the following quick hack works for my needs, call this just after posting...
someViewModel.SomeDictionary = (from object key in Request.Form.Keys
where key.ToString().StartsWith("SomeDictionary[")
select new
{
Key = key.ToString().Replace("SomeDictionary[", string.Empty).Replace("]", string.Empty),
Value = (object)Request.Form[key.ToString()]
}).ToDictionary(arg => arg.Key, arg1 => arg1.Value);
It needs some tidying up ofcourse :)
You may take a look at this post to see how dictionaries should be binded. I am afraid that using strongly typed EditorFor helpers you won't be able to achieve this and you will have to generate the fields manually.
Say I have this repeater which makes use of a public function called Test in the code-behind.
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("MyCol1")%></td>
<td><%# Eval("MyCol2")%></td>
<td><%# Test((int)Eval("MyCol1"))%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
In my code-behind, I have this function
public string Test (int Value)
{
return "Test"+Value.ToString();
}
This works fine but in my website I will have similar repeaters on various pages and most of them will need to call the Test function. Instead of having it in the code-behind of each web page would it be possible to put it in a public static class and call it directly from the repeater? Something like this (which does not work):
<td><%# MyStaticClass.Test((int)Eval("MyCol1"))%></td>
The only solution I've come up with would be to change the function in the code-behind to:
public string Test (int Value)
{
return MyStaticClass.Test(Value);
}
But it would be neater if I didn't have to put any code in the code-behind of each webpage (ie I would prefer the repeater to call the static function directly).
Any ideas or suggestions?
Create a Base class for your pages and put your common function there. So it will be available for all inherited child pages.
Can't
<td><%# Test((int)Eval("MyCol1"))%></td>
Be represented by
<td><%# Eval("MyCol1", "Test: {0}") %></td>
Or is there more to your test function that that?
I typically create a class for shared/static functions in my websites. This class can then be called from any page in the site and allows the code to be seperated from your UI or presentation code.
clsGlobal.cs
namespace testClass
{
public class clsGlobal
{
public static int EvalNumber(int value){
int localInt = 5;
return localInt + value;
}
}
}
Default.aspx
Option 1
This version imports the namespace of the global class into the aspx page so you can reference your static functions without using the namespace. "clsGlobal.EvelMethod()"
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="testClass._Default" %>
<%# Import Namespace="testClass" %>
<!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>Static Class Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%= clsGlobal.EvalNumber(5).ToString() %>
</div>
</form>
</body>
</html>
Default.aspx
Option 2
This version calls the static function using the fully qualified function name including the namespace. "testClass.clsGlobal.EvalNumber()"
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="testClass._Default" %>
<!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>Static Class Example</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%= testClass.clsGlobal.EvalNumber(5).ToString() %>
</div>
</form>
</body>
</html>
Do you use a master page? You could drop it in there if you do.
I would do something like this:
On every content page that inherits from the master page you need:
<%# MasterType VirtualPath="[path to your master page]" %>
This allows you to get to the public methods on the master.
On your content page, whenever you need to call the Test method:
Master.Test([your int value]);
The accepted answer, and other answers here, suggest that inheritance is necessary to solve this problem. This confused me, so I asked my own question - How to call functions in a Class file, when inside a Repeater, without inheritance - and thanks to #Walsharoo I found out I merely needed to add the Project Name and I could call a static function (in a Class) from inside a repeater:
<td><%# [ProjectName].ClassName.MyStaticFunction(Eval("MyColumnName"))%></td>
This may prove helpful to others, I hope, though I'm not suggesting you're all as daft as me for forgetting this simple trick.