Làm thế nào để truy xuất các giá trị biểu mẫu từ HTTPPOST, từ điển hoặc?


112

Tôi có bộ điều khiển MVC có Phương pháp hành động này:

[HttpPost]
public ActionResult SubmitAction()
{
     // Get Post Params Here
 ... return something ...
}

Biểu mẫu là một biểu mẫu không tầm thường với một hộp văn bản đơn giản.

Câu hỏi

Làm cách nào để truy cập các giá trị tham số?

Tôi không đăng bài từ Chế độ xem, bài đăng đến từ bên ngoài. Tôi giả sử có một bộ sưu tập các cặp khóa / giá trị mà tôi có quyền truy cập.

Tôi đã thử Request.Params.Get("simpleTextBox");nhưng nó trả về lỗi "Xin lỗi, đã xảy ra lỗi khi xử lý yêu cầu của bạn.".

Câu trả lời:


155

Bạn có thể yêu cầu hành động của bộ điều khiển lấy một đối tượng phản ánh tên đầu vào của biểu mẫu và trình kết nối mô hình mặc định sẽ tự động tạo đối tượng này cho bạn:

[HttpPost]
public ActionResult SubmitAction(SomeModel model)
{
    var value1 = model.SimpleProp1;
    var value2 = model.SimpleProp2;
    var value3 = model.ComplexProp1.SimpleProp1;
    ...

    ... return something ...
}

Một cách khác (rõ ràng là xấu hơn) là:

[HttpPost]
public ActionResult SubmitAction()
{
    var value1 = Request["SimpleProp1"];
    var value2 = Request["SimpleProp2"];
    var value3 = Request["ComplexProp1.SimpleProp1"];
    ...

    ... return something ...
}

5
Tôi chỉ muốn chỉ ra rằng bạn mất bản sao lưu của trình biên dịch trong tùy chọn 2. Nếu mô hình thay đổi, trình biên dịch sẽ không nắm bắt được sự thay đổi trong các bộ điều khiển liên quan. Có những trường hợp tốt cho tùy chọn 2 nhưng tôi không khuyến khích sử dụng rộng rãi.
Serguei Fedorov

1
Đôi khi bạn cần những thứ xấu xí, thật tốt để có lựa chọn khi bạn đã biết các phương pháp hay nhất là gì
Oscar Ortiz

Như một người vẫn đang học dot net, tại sao cách thứ hai lại xấu hơn?
Goose

3
@ Goose, bởi vì nó là chuỗi ma thuật. Bạn không nhận được bất kỳ sự an toàn về thời gian biên dịch. Mã của bạn sẽ bị lỗi trong thời gian chạy nếu bạn mắc lỗi đánh máy trong tên của biến trong khi nếu bạn sử dụng kiểu gõ mạnh, trình biên dịch sẽ là bạn của bạn.
Darin Dimitrov

@DarinDimitrov có lý. Khác với thế giới tôi đến. Tính năng rất hay.
Goose

104

Đơn giản, bạn có thể sử dụng FormCollectionnhư:

[HttpPost] 
public ActionResult SubmitAction(FormCollection collection)
{
     // Get Post Params Here
 string var1 = collection["var1"];
}

Bạn cũng có thể sử dụng một lớp, được ánh xạ với giá trị Biểu mẫu và công cụ mvc asp.net tự động điền vào nó:

//Defined in another file
class MyForm
{
  public string var1 { get; set; }
}

[HttpPost]
public ActionResult SubmitAction(MyForm form)
{      
  string var1 = form1.Var1;
}

tôi thích giải pháp lớp học của nó dễ dàng và đơn giản
Basheer AL-MOMANI

36

Các câu trả lời là rất tốt nhưng có một cách khác trong bản phát hành mới nhất của MVC và .NET mà tôi thực sự thích sử dụng, thay vì các phím FormCollection và Request "kiểu cũ".


Hãy xem xét một đoạn mã HTML chứa trong thẻ biểu mẫu thực hiện AJAX hoặc ĐĂNG MẪU.

<input type="hidden"   name="TrackingID" 
<input type="text"     name="FirstName"  id="firstnametext" />
<input type="checkbox" name="IsLegal"  value="Do you accept terms and conditions?" />

Bộ điều khiển của bạn sẽ thực sự phân tích cú pháp dữ liệu biểu mẫu và cố gắng cung cấp nó cho bạn dưới dạng các tham số của kiểu đã xác định. Tôi đã bao gồm hộp kiểm vì nó là một hộp kiểm phức tạp. Nó trả về văn bản "on" nếu được chọn và null nếu không được chọn. Tuy nhiên, yêu cầu là các biến được xác định này PHẢI tồn tại (trừ khi có giá trị nullable (hãy nhớ mặc dù điều đó stringlà nullable)) nếu không thì việc quay lại AJAX hoặc POST sẽ không thành công.

[HttpPost]
public ActionResult PostBack(int TrackingID, string FirstName, string IsLegal){
    MyData.SaveRequest(TrackingID,FirstName, IsLegal == null ? false : true);
}

Bạn cũng có thể đăng lại một mô hình mà không cần sử dụng bất kỳ trợ giúp dao cạo nào. Tôi đã nhận ra rằng điều này là cần thiết một số lần.

public Class HomeModel
{
  public int HouseNumber { get; set; }
  public string StreetAddress { get; set; }
}

Đánh dấu HTML sẽ đơn giản là ...

<input type="text" name="variableName.HouseNumber" id="whateverid" >

và bộ điều khiển của bạn (Razor Engine) sẽ chặn "Tên biến" của Biến biểu mẫu (tên tùy thích nhưng giữ nó nhất quán) và cố gắng xây dựng và truyền nó tới MyModel.

[HttpPost]
public ActionResult PostBack(HomeModel variableName){
    postBack.HouseNumber; //The value user entered
    postBack.StreetAddress; //the default value of NULL.
}

Khi bộ điều khiển đang mong đợi một Model (trong trường hợp này là HomeModel), bạn không cần phải xác định TẤT CẢ các trường vì trình phân tích cú pháp sẽ để chúng ở chế độ mặc định, thường là NULL. Điều thú vị là bạn có thể kết hợp và kết hợp các mô hình khác nhau trên Mark-up và phân tích cú pháp sau đăng sẽ phổ biến nhất có thể. Bạn không cần xác định mô hình trên trang hoặc sử dụng bất kỳ trình trợ giúp nào.

MẸO: Tên của tham số trong bộ điều khiển là tên được xác định trong mã đánh dấu HTML "name =" không phải tên của Model mà là tên của biến mong đợi trong!


Việc sử dụng List<>phức tạp hơn một chút trong việc đánh dấu.

<input type="text" name="variableNameHere[0].HouseNumber" id="id"           value="0">
<input type="text" name="variableNameHere[1].HouseNumber" id="whateverid-x" value="1">
<input type="text" name="variableNameHere[2].HouseNumber"                   value="2">
<input type="text" name="variableNameHere[3].HouseNumber" id="whateverid22" value="3">

Chỉ mục trên Danh sách <> PHẢI luôn luôn dựa trên 0 và tuần tự. 0,1,2,3.

[HttpPost]
public ActionResult PostBack(List<HomeModel> variableNameHere){
     int counter = MyHomes.Count()
     foreach(var home in MyHomes)
     { ... }
}

Sử dụng IEnumerable<>cho các chỉ số dựa trên không và không tuần tự đăng lại. Chúng ta cần thêm một đầu vào ẩn bổ sung để giúp kết dính.

<input type="hidden" name="variableNameHere.Index" value="278">
<input type="text" name="variableNameHere[278].HouseNumber" id="id"      value="3">

<input type="hidden" name="variableNameHere.Index" value="99976">
<input type="text" name="variableNameHere[99976].HouseNumber" id="id3"   value="4">

<input type="hidden" name="variableNameHere.Index" value="777">
<input type="text" name="variableNameHere[777].HouseNumber" id="id23"    value="5">

Và mã chỉ cần sử dụng IEnumerable và gọi ToList()

[HttpPost]
public ActionResult PostBack(IEnumerable<MyModel> variableNameHere){
     int counter = variableNameHere.ToList().Count()
     foreach(var home in variableNameHere)
     { ... }
}

Bạn nên sử dụng một Mô hình duy nhất hoặc một ViewModel (Mô hình nối các mô hình khác để tạo Mô hình 'Chế độ xem' phức tạp) trên mỗi trang. Trộn và kết hợp như đã đề xuất có thể được coi là thực hành xấu, nhưng miễn là nó hoạt động và có thể đọc được thì nó không XẤU. Tuy nhiên, nó chứng tỏ sức mạnh và tính linh hoạt của động cơ Razor.

Vì vậy, nếu bạn cần thêm thứ gì đó tùy ý hoặc ghi đè giá trị khác từ trình trợ giúp Razor hoặc không muốn tạo trợ giúp của riêng bạn, đối với một biểu mẫu sử dụng một số kết hợp dữ liệu bất thường, bạn có thể nhanh chóng sử dụng các phương pháp này để chấp nhận thêm dữ liệu.


Sử dụng tùy chọn Chỉ mục là tối nghĩa. Ai trên trái đất xanh của Chúa sẽ biết sử dụng thứ đó hoặc nó thậm chí còn tồn tại ?! Nhưng, tôi rất vui vì tôi đã tìm thấy bài đăng này. Nó sẽ tiết kiệm rất nhiều lưu lượng mạng.
Michael Silver

1
Điều này hiệu quả với tôi nhưng chỉ sau khi tôi thay đổi <input type = "hidden" id = "myId"> thành @ Html.Hidden ("myId")
radkan

@Piotr - vui lòng sửa lỗi tham chiếu của bạn không nhất quán với MyModel và MyHomes. Nó gây ra sự nhầm lẫn như thế nào là hiện tại.
Spencer Sullivan

15

Nếu bạn muốn lấy dữ liệu biểu mẫu trực tiếp từ yêu cầu Http mà không có bất kỳ ràng buộc mô hình nào hoặc FormCollectionbạn có thể sử dụng điều này:

[HttpPost] 
public ActionResult SubmitAction() {

    // This will return an string array of all keys in the form.
    // NOTE: you specify the keys in form by the name attributes e.g:
    // <input name="this is the key" value="some value" type="test" />
    var keys = Request.Form.AllKeys;

    // This will return the value for the keys.
    var value1 = Request.Form.Get(keys[0]);
    var value2 = Request.Form.Get(keys[1]);
}

2
Lưu ý rằng đây có thể là biểu mẫu xấu (không có ý định chơi chữ) nhưng đôi khi bạn chỉ muốn các giá trị biểu mẫu và bạn không thể thay đổi rõ ràng chữ ký hàm. Đây là giải pháp duy nhất ở đây phù hợp với tình huống cụ thể của tôi.
Ryan

Làm thế nào để kiểm tra đơn vị phương pháp này với các tham chiếu tĩnh đó? FormCollection sẽ đáng mong đợi hơn khi nói đến thử nghiệm.
Kees de Wit,

@KeesdeWit nếu bạn đọc nhận xét trước đây không phải là cách tốt nhất, nhưng đôi khi sử dụng như một cách giải quyết. Để kiểm tra đơn vị, có thể bạn có thể giả lập Requestvà đưa nó vào phương thức.
A-Sharabiani
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.