24

我很确定我在这里做错了什么。在过去的两个月里,我们一直在使用 MVC 和 Razor 开发一个 Web 应用程序,我们从未想过使用表单元素。现在已经对母版页和子页做了很多工作,这意味着重组我们的大部分代码以使用表单元素,这将导致页面上有多个表单元素。

除此之外,在 Asp.Net 中,如果我想访问后面的 C# 代码中的任何控件,我可以给它一个 ID="SomeID" 和一个 RUNAT="SERVER"。然后在我后面的代码中,我可以设置它的值和属性。

当我在 Razor 中执行此操作时,我们使用如下行:

 <input id="hiddenPostBack" runat="server" type="hidden" />

为什么我不能在控制器中访问它?如果是第一次加载页面,我想检测回发并将值设置为 false,如果不是,则将值设置为 true。然后基于此,我将在服务器端或客户端读取它并做一些事情。

我真正的问题是,鉴于我没有表单元素,我如何在服务器端和客户端“做某事”。我的印象是,如果我想将值从客户端传递到服务器并返回,最简单的方法是使用隐藏输入。但我只是不知道如何使用 MVC3 和 razor 来实现这一点。

在此先感谢您的帮助。

4

5 回答 5

40

从 WebForms 到 MVC 的转变需要对逻辑和大脑过程进行彻底的改变。您不再与服务器端和客户端的“表单”交互(事实上,即使使用 WebForms,您也没有与客户端交互)。您可能只是在其中混杂了一些想法,因为您只是在与 Web 页面的构建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。

于 2012-07-04T09:10:36.473 回答
10

如果您使用的是 Razor,则无法直接访问该字段,但可以管理其值。

这个想法是,第一个 Microsoft 方法驱使开发人员远离 Web 开发,并使桌面程序员(例如)更容易制作 Web 应用程序。

同时,Web 开发人员并不了解 ASP.NET 这种诡谲诡异的方式。

实际上,这个隐藏的输入是在客户端呈现的,而 ASP 无法访问它(它从来没有)。但是,随着时间的推移,您会看到它是一种盗版方式,并且当您使用它时,您可能会依赖它。Web 开发不同于桌面或移动。

模型是您的逻辑单元,隐藏字段(和整个视图页面)只是数据的代表视图。因此,您可以将您的工作专门用于应用程序或域逻辑,而视图只是将其提供给消费者 - 这意味着您不需要视图中的详细访问和“头脑风暴”功能。

控制器实际上确实可以管理隐藏或常规设置。模型提供特定的逻辑单元属性和功能,而视图只是将其呈现给最终用户,简单地说。阅读有关MVC的更多信息。

模型

public class MyClassModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string MyPropertyForHidden { get; set; }
}

这是控制器动作

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 是视图的某种数据载体。它不限制您使用模型 - 您可以放置​​任何您喜欢的东西。

于 2012-07-04T09:41:51.783 回答
1

您可能已经想到,Asp.Net MVC 是不同于 Asp.Net(webforms)的范式。在服务器和客户端之间访问表单元素在 Asp.Net MVC 中采用了不同的方法。

您可以在网上搜索更多关于此的阅读材料。目前,我建议使用 Ajax 来获取或发布数据到服务器。您仍然可以使用input type="hidden",但使用ViewDataRazor 的 或 的值对其进行初始化,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
});

您也可以使用$.ajax, $.getJSON$.post具体取决于您的要求。

于 2012-07-04T09:09:23.383 回答
0

首先,ASP.NET MVC 的工作方式与 WebForms 不同。你没有全部runat="server"。MVC 不提供 WebForms 提供的抽象层。可能您应该尝试了解控制器和操作是什么,然后您应该查看模型绑定。任何关于 MVC 的初学者教程都展示了如何在客户端和服务器之间传递数据。

于 2012-07-04T09:04:20.877 回答
-1

您做错了,因为您尝试在 MVC 应用程序中映射 WebForms。

MVC 中没有服务器端控件。后端只有ViewController 。您通过使用模型初始化视图将数据从服务器发送到客户端。

这发生在对您的资源的 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();
}
于 2012-07-04T09:09:07.003 回答