我很确定我在这里做错了什么。在过去的两个月里,我们一直在使用MVC和Razor开发一个Web应用程序,我们从未想过使用表单元素。现在已经完成了母版页和子页面的大量工作,这意味着重构我们的大部分代码以便使用表单元素,这会在页面上产生多个表单元素。
除此之外,在Asp.Net中,如果我想访问后面的C#代码中的任何控件,我可以给它一个ID =“SomeID”和一个RUNAT =“SERVER”。然后在我的代码后面我可以设置它的值和属性。
当我在Razor中执行此操作时,我们使用以下行:
<input id="hiddenPostBack" runat="server" type="hidden" />
为什么我无法在控制器中访问它?我想检测回发并将值设置为false,如果它是第一次加载页面,如果没有,则将值设置为true。然后基于此,我将在服务器端或客户端读取它并做一些事情。
我真正的问题是,如果我没有表单元素,我如何在服务器端和客户端“做某事”。我的印象是,如果我想将值从客户端传递到服务器并返回,最简单的方法是使用隐藏输入。但我只是没有通过MVC3和剃刀来实现这一目标。
提前感谢您的帮助。
答案 0 :(得分:35)
从WebForms迁移到MVC需要在逻辑和大脑过程中进行彻底的改变。您不再需要与服务器端和客户端的“表单”进行交互(实际上即使使用WebForms,您也没有与客户端进行交互)。你可能只是想到了一点,那就是使用WebForms和RUNAT="SERVER"
,你只是在与网页的构建进行交互。
MVC有点类似,因为你在构建模型时需要服务器端代码(你需要构建用户将看到的数据),但是一旦你构建了HTML,你需要了解服务器之间的链接并且用户不再存在。他们有一页HTML,就是这样。
因此,您正在构建的HTML是只读。您将模型传递到Razor页面,该页面将构建适合该模型的HTML。
如果你想拥有一个设置为true或false的隐藏元素,具体取决于这是否是第一个视图,你需要在模型中使用bool,并在Action中将其设置为True,如果它是为了跟进。这可以通过根据请求是[HttpGet]还是[HttpPost]进行不同的操作来完成(如果这适合您设置表单的方式:第一次访问的GET请求和提交表单时的POST请求)。
或者,模型在创建时可以设置为True(这是您第一次访问页面时),但在之后将值检查为True或False(因为bool默认值)当它被实例化时为False)。然后使用:
@Html.HiddenFor(x => x.HiddenPostBack)
在你的表单中,这将隐藏True。当表单回发到您的服务器时,模型现在将该值设置为True。
很难提供更多的建议,因为你的问题并非具体到为什么你想要这样做。您可以阅读一本关于从WebForms迁移到MVC的好书,例如Steve Sanderson的Pro ASP.NET MVC。
答案 1 :(得分:8)
如果您使用的是Razor,则无法直接访问该字段,但可以管理其值。
这个想法是,第一个Microsoft方法驱使开发人员远离Web开发,并使桌面程序员(例如)可以轻松制作Web应用程序。
与此同时,Web开发人员并不了解这种棘手的ASP.NET方式。
实际上这个隐藏的输入是在客户端呈现的,ASP无法访问它(它从来没有)。然而,随着时间的推移,你会看到它的海盗方式,你可以依赖它,当你使用它。 Web开发与Desktop或Mobile不同。
模型是您的逻辑单元,隐藏字段(以及整个视图页面)只是数据的代表性视图。因此,您可以专注于应用程序或域逻辑,视图只是为消费者提供服务 - 这意味着您无需在视图中进行详细访问和“头脑风暴”功能。
控制器实际上可以帮助您管理隐藏或常规设置。该模型提供特定的逻辑单元属性和功能,视图只是将它呈现给最终用户,简单地说。详细了解MVC。
模型
public class MyClassModel
{
public int Id { get; set; }
public string Name { get; set; }
public string MyPropertyForHidden { get; set; }
}
这是控制器aciton
public ActionResult MyPageView()
{
MyClassModel model = new MyClassModel(); // Single entity, strongly-typed
// IList model = new List<MyClassModel>(); // or List, strongly-typed
// ViewBag.MyHiddenInputValue = "Something to pass"; // ...or using ViewBag
return View(model);
}
视图如下
//This will make a Model property of the View to be of MyClassModel
@model MyNamespace.Models.MyClassModel // strongly-typed view
// @model IList<MyNamespace.Models.MyClassModel> // list, strongly-typed view
// ... Some Other Code ...
@using(Html.BeginForm()) // Creates <form>
{
// Renders hidden field for your model property (strongly-typed)
// The field rendered to server your model property (Address, Phone, etc.)
Html.HiddenFor(model => Model.MyPropertyForHidden);
// For list you may use foreach on Model
// foreach(var item in Model) or foreach(MyClassModel item in Model)
}
// ... Some Other Code ...
ViewBag视图:
// ... Some Other Code ...
@using(Html.BeginForm()) // Creates <form>
{
Html.Hidden(
"HiddenName",
ViewBag.MyHiddenInputValue,
new { @class = "hiddencss", maxlength = 255 /*, etc... */ }
);
}
// ... Some Other Code ...
我们正在使用Html Helper渲染隐藏字段,或者我们也可以手工编写它 - <input name=".." id=".." value="ViewBag.MyHiddenInputValue">
。
ViewBag是视图的某种数据载体。它不会限制你的模特 - 你可以放置你喜欢的任何东西。
答案 2 :(得分:1)
正如您可能已经想到的那样,Asp.Net MVC是一个与Asp.Net(webforms)不同的范例。访问服务器和客户端之间的表单元素在Asp.Net MVC中采用不同的方法。
您可以在网上搜索更多阅读材料。现在,我建议使用Ajax来获取或发布数据到服务器。您仍然可以使用input type="hidden"
,但可以使用ViewData
或Razor ViewBag
中的值对其进行初始化。
例如,您的控制器可能如下所示:
public ActionResult Index()
{
ViewBag.MyInitialValue = true;
return View();
}
在您看来,您可以拥有一个由ViewBag
中的值初始化的输入元素:
<input type="hidden" name="myHiddenInput" id="myHiddenInput" value="@ViewBag.MyInitialValue" />
然后,您可以通过ajax在客户端和服务器之间传递数据。例如,使用jQuery:
$.get('GetMyNewValue?oldValue=' + $('#myHiddenInput').val(), function (e) {
// blah
});
答案 3 :(得分:0)
首先,ASP.NET MVC的工作方式与WebForms的工作方式不同。你没有整个runat="server"
的东西。 MVC不提供WebForms提供的抽象层。 Probabaly你应该尝试了解控制器和操作是什么,然后你应该看看模型绑定。任何关于MVC的初级教程都会展示如何在客户端和服务器之间传递数据。
答案 4 :(得分:-1)
自从尝试在MVC应用程序中映射WebForms以来,你做错了。
MVC中没有服务器端控件。只有查看和 后端有控制器。您将数据从服务器发送到客户端 用你的模型初始化View的方法。
这发生在对资源的HTTP GET请求中。
[HttpGet]
public ActionResult Home()
{
var model = new HomeModel { Greeatings = "Hi" };
return View(model);
}
您可以通过发布数据将数据从客户端发送到服务器 服务器。要实现这一点,您需要在视图中创建一个表单
中的[HttpPost]
处理程序
// View
@using (Html.BeginForm()) {
@Html.TextBoxFor(m => m.Name)
@Html.TextBoxFor(m => m.Password)
}
// Controller
[HttpPost]
public ActionResult Home(LoginModel model)
{
// do auth.. and stuff
return Redirect();
}