2017-06-23 17 views
10

Bit của một trường hợp lạ đối với bất kỳ ai có suy nghĩ về nó… Tôi đang hiển thị trường Boolean ẩn trên một trang cụ thể. Tuy nhiên, tôi nhận được hai đánh dấu hơi khác nhau cho cùng một lĩnh vực tùy thuộc vào việc một sự kiện cụ thể đã xảy ra trước đó trong quá trình. Hai trường được tạo ra là;Trường Boolean được hiển thị với các trường hợp khác nhau

<input id="HasPreviouslyIssuedCard" name="HasPreviouslyIssuedCard" type="hidden" value="false" /> 

<input id="HasPreviouslyIssuedCard" name="HasPreviouslyIssuedCard" type="hidden" value="False" /> 

Vấn đề là trường hợp của các văn bản trong “giá trị” thuộc tính mà bạn sẽ nhận thấy là khác nhau và sau đó ảnh hưởng đến điều kiện JS. Việc đánh dấu dao cạo tạo ra điều này là;

@Html.Hidden("HasPreviouslyIssuedCard", Model.HasPreviouslyIssuedCard?.ToString(), new { id = nameof(Model.HasPreviouslyIssuedCard) }) 

Tuy nhiên, tôi cũng đã thử một biến thể bằng cách sử dụng sự khác biệt tương tự trong hiển thị trường ẩn;

@Html.HiddenFor(m => m.HasPreviouslyIssuedCard) 

Tôi nên làm gì để có sự khác biệt này? Để có được biến thể chữ hoa, tôi nhấn nút Quay lại trình duyệt trước khi đến trang có liên quan. Cả hai phương thức tải dữ liệu theo cùng một cách và chuyển cùng một giá trị vào trình kết xuất theo cùng một cách. Hai đầu ra khác nhau.

Hãy nhớ rằng đây là trường boolean, kiểu giá trị được hiển thị. Không nên có nhiều phạm vi để tinker với. Có nhiều cách để giải quyết vấn đề này nhưng vì chúng tôi có một vài mục về việc tồn đọng liên quan đến các trường boolean và nút quay lại, tôi muốn giải thích điều này thay vì làm việc xung quanh nó. Dự đoán tốt nhất của tôi là nhấn nút quay lại bằng cách nào đó thay đổi trạng thái của trình kết xuất hoặc một số cờ khác trong mô hình khác (có hơn 70 trường là thuật sĩ) đang thay đổi cách trình kết xuất diễn giải như thế nào để trường hợp giá trị boolean. Giá trị là như nhau, trang giống nhau, dữ liệu được đọc theo cùng một cách.

Dựa trên trang này (Why does Boolean.ToString output "True" and not "true"), chúng ta nên giả định là nhận được biến thể chữ hoa tất cả các thời gian nhưng điều này không phải là kết quả.

Bất kỳ người tạo/ý tưởng/suy nghĩ nào?

EDIT 1

Đào thông qua logic vẽ MVC trong HiddenFor() phương pháp, cuối cùng Convert.ToString(value, CultureInfo.CurrentCulture) được gọi. Tôi không thể có được điều này để sản xuất một boolean trường hợp thấp hơn khi được gọi trực tiếp, nhưng rõ ràng là làm như vậy. Mã văn hóa hiện tại của tôi được đặt thành en-IE nhưng tôi thấy giá trị boolean chữ hoa khi gọi trực tiếp.

EDIT 2

tôi đã thực hiện nhiều hơn một chút mày mò và truy tìm thông qua ứng dụng của tôi và có thể cung cấp một chi tiết chút về những gì đang xảy ra mặc dù tôi vẫn chưa thể tái sản xuất này trong một đơn giản hơn ứng dụng.

MVC 5 Ứng dụng: Có;

  1. Trang đích ban đầu có URL đích tại miền gốc / được truy xuất qua HTTP GET.Thẻ Boolean input hiển thị dưới dạng True/False
  2. Trang đầu tiên trong trình hướng dẫn tại URL /Apply được truy xuất qua HTTP GET. Thẻ Boolean input hiển thị dưới dạng True/False
  3. Trang thứ hai trong trình hướng dẫn tại cùng một URL sau khi người dùng gửi trang ở bước 2. Truy xuất qua HTTP POST. Hiện tại, các thẻ input hiển thị là true/false.
  4. Nhấn nút Quay lại của trình duyệt và nhấn trang bẫy (chúng tôi đặt lịch sử trình duyệt để luôn truy cập trang bẫy trên Quay lại khi phát nội dung thú vị với trình hướng dẫn).
  5. Nút lần truy cập của người dùng trên trang bẫy để đưa họ trở lại ứng dụng mà họ đã dừng lại. input thẻ hiện đang hiển thị lại ở dạng chữ hoa (vấn đề được báo cáo ban đầu).

Tôi đã đào sâu vào các thư viện MVC sử dụng ILSpy để thử và quét qua và MVC (nếu tôi đọc mã chính xác) thực sự sử dụng một thực hiện IConverter để viết giá trị boolean, không Convert.ToString(value, CultureInfo.CurrentCulture) như tôi ban đầu nghĩ.

Ngăn xếp mã truy tìm từ cuộc gọi đến HiddenFor() là (tôi nghĩ);

  1. System.Web.Mvc.InputExtentions.HiddenFor() (public function)
  2. System.Web.Mvc.InputExtentions.HiddenHelper() (chức năng riêng, một số logic vào đây để mảng nhưng không áp dụng trong trường hợp của chúng tôi)
  3. System.Web.Mvc.InputExtentions.InputHelper() (chức năng riêng, kỳ diệu xảy ra ở đây)

Mã được biên dịch cho System.Web.Mvc.InputExtentions.InputHelper();

private static MvcHtmlString InputHelper(HtmlHelper htmlHelper, InputType inputType, ModelMetadata metadata, string name, object value, bool useViewData, bool isChecked, bool setId, bool isExplicitValue, string format, IDictionary<string, object> htmlAttributes) 
{ 
    string fullHtmlFieldName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name); 
    if (string.IsNullOrEmpty(fullHtmlFieldName)) 
    { 
     throw new ArgumentException(MvcResources.Common_NullOrEmpty, "name"); 
    } 
    TagBuilder tagBuilder = new TagBuilder("input"); 
    tagBuilder.MergeAttributes<string, object>(htmlAttributes); 
    tagBuilder.MergeAttribute("type", HtmlHelper.GetInputTypeString(inputType)); 
    tagBuilder.MergeAttribute("name", fullHtmlFieldName, true); 
    string text = htmlHelper.FormatValue(value, format); 
    bool flag = false; 
    switch (inputType) 
    { 
    case InputType.CheckBox: 
    { 
     bool? flag2 = htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof(bool)) as bool?; 
     if (flag2.HasValue) 
     { 
      isChecked = flag2.Value; 
      flag = true; 
     } 
     break; 
    } 
    case InputType.Hidden: 
     goto IL_131; 
    case InputType.Password: 
     if (value != null) 
     { 
      tagBuilder.MergeAttribute("value", text, isExplicitValue); 
      goto IL_16C; 
     } 
     goto IL_16C; 
    case InputType.Radio: 
     break; 
    default: 
     goto IL_131; 
    } 
    if (!flag) 
    { 
     string text2 = htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof(string)) as string; 
     if (text2 != null) 
     { 
      isChecked = string.Equals(text2, text, StringComparison.Ordinal); 
      flag = true; 
     } 
    } 
    if (!flag && useViewData) 
    { 
     isChecked = htmlHelper.EvalBoolean(fullHtmlFieldName); 
    } 
    if (isChecked) 
    { 
     tagBuilder.MergeAttribute("checked", "checked"); 
    } 
    tagBuilder.MergeAttribute("value", text, isExplicitValue); 
    goto IL_16C; 
    IL_131: 
    string text3 = (string)htmlHelper.GetModelStateValue(fullHtmlFieldName, typeof(string)); 
    tagBuilder.MergeAttribute("value", text3 ?? (useViewData ? htmlHelper.EvalString(fullHtmlFieldName, format) : text), isExplicitValue); 
    IL_16C: 
    if (setId) 
    { 
     tagBuilder.GenerateId(fullHtmlFieldName); 
    } 
    ModelState modelState; 
    if (htmlHelper.ViewData.ModelState.TryGetValue(fullHtmlFieldName, out modelState) && modelState.Errors.Count > 0) 
    { 
     tagBuilder.AddCssClass(HtmlHelper.ValidationInputCssClassName); 
    } 
    tagBuilder.MergeAttributes<string, object>(htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata)); 
    if (inputType == InputType.CheckBox) 
    { 
     StringBuilder stringBuilder = new StringBuilder(); 
     stringBuilder.Append(tagBuilder.ToString(TagRenderMode.SelfClosing)); 
     TagBuilder tagBuilder2 = new TagBuilder("input"); 
     tagBuilder2.MergeAttribute("type", HtmlHelper.GetInputTypeString(InputType.Hidden)); 
     tagBuilder2.MergeAttribute("name", fullHtmlFieldName); 
     tagBuilder2.MergeAttribute("value", "false"); 
     stringBuilder.Append(tagBuilder2.ToString(TagRenderMode.SelfClosing)); 
     return MvcHtmlString.Create(stringBuilder.ToString()); 
    } 
    return tagBuilder.ToMvcHtmlString(TagRenderMode.SelfClosing); 
} 

EDIT 3

Chỉ cần để xác định lại như có một vài ý kiến ​​về bên javascript của sự vật. Tôi đã xem xét điều này sớm trong việc cố gắng chẩn đoán vấn đề. Để loại trừ bất kỳ sự can thiệp/thao tác JS tiềm năng nào, tôi đã sử dụng Fiddler để nắm bắt HTML trong quá trình truyền. HTML mà MVC đang tạo ra đang thay đổi trường hợp - và tôi có thể thấy điều này trong Fiddler, tại một điểm trước khi JS thậm chí tải, không bao giờ chạy. Nó không phải là một vấn đề JS.

+0

Không liên quan nhưng nó chỉ '@ Html.Hidden ("HasPreviouslyIssuedCard")' - mà sẽ tạo ra 'giá trị' và 'id' thuộc tính giống như' @ Html.HiddenFor (m => m.HasPreviouslyIssuedCard) ' –

+0

@StephenMuecke đó là do thiết kế – DiskJunky

+0

Không thể nào có thể có một tập lệnh đang chạy thay đổi giá trị của trường ẩn này? – brijber

Trả lời

3

Có vẻ như tôi đã sai, trước hết, JS, mặc dù không phải lúc tôi đang cố gắng loại trừ nó.Trình tự của các sự kiện để tái sản xuất này;

  1. Tạo HTML form với boolean lĩnh vực ẩn + không nút gửi
  2. Trong trường hợp onclick cho nút, có một mảnh JS mà bộ lĩnh vực boolean để true (chữ thường)
  3. Trong POST của bạn hành động trong bộ điều khiển, hiển thị cùng một chế độ xem

Sau POST trường boolean sẽ có giá trị chữ thường thay vì chữ hoa.

Điều gì đang xảy ra? Vâng, HiddenFor() (và các biến thể của nó) sẽ hiển thị giá trị boolean từ ViewData.ModelState thay vì giá trị boolean của mô hình nếu nó có trong bộ sưu tập ModelState. Có vẻ trực quan nhưng những gì có thể (và đã làm cho tôi) ném bạn là tất cả các loại dữ liệu khác, chất kết dính mô hình khá cụ thể - giá trị ModelState và giá trị thuộc tính của mô hình của bạn sẽ giống nhau. Ngoại trừ trong trường hợp cho boolean - chất kết dính mô hình đủ thông minh để xử lý Truetrue giống nhau nhưng điều này làm cho giá trị ModelState và giá trị thuộc tính được xâu chuỗi của bạn không xuất hiện nếu được đặt qua boolean JS. Đối với lý do tại sao điều này đặt lại cho tôi sau khi nhấn nút Back của trình duyệt - trang bẫy mà chúng tôi không có giá trị biểu mẫu và liên kết ngược lại vào ứng dụng qua HTTP GET gây ra HiddenFor để gọi thuộc tính mô hình .ToString() thay vì hơn là kéo nó từ ModelState vì nó không có trong đó tại thời điểm đó. Tương tự như vậy, trong các thử nghiệm của tôi, người dùng sẽ ở một điểm trong trình hướng dẫn dài sau khi nó sẽ được thiết lập thông qua JS, vì vậy nó sẽ ở dạng chữ hoa khi chúng tiếp tục thông qua trình hướng dẫn.

Giả định của tôi là JS đang khởi động sau khi trang được tải. Nó thực sự là do JS thiết lập một giá trị trước khi khởi động POST và giá trị trường hợp thấp hơn đó vẫn tồn tại qua vòng đời trang qua ModelState. Đi con số.

EDIT

Mã để tái tạo;

Mô hình;

public class Test 
{ 
    public bool Sample { get; set; } 
} 

Đánh dấu dao cạo;

@model TestModelValueCase.Models.Test 
@{ 
    ViewBag.Title = "Test Page"; 
} 

@using (Html.BeginForm()) 
{ 
    @Html.HiddenFor(m => m.Sample) 
    <div> 
     <label>Hidden Value:</label> 
     <span id="_uiValue"></span> 
    </div> 
    <button type="submit">Try Post</button> 
} 
@section scripts 
{ 
    <script type="text/javascript" language="javascript"> 
     $(document).ready(function() { 
      var source = $('#@nameof(Model.Sample)'); 
      $('#_uiValue').html(source.val()); 
      source.val(true); 
     }); 
    </script> 
} 

Bộ điều khiển;

public ActionResult Index() 
    { 
     Test model = new Test(); 
     return View(model); 
    } 

    [HttpPost] 
    public ActionResult Index(Test model) 
    { 
     return View(model); 
    } 
0

Trường hợp boolean bắt nguồn từ bộ điều khiển là rất phức tạp vì phần lớn thời gian được hiểu là chuỗi.

Trường hợp này có vẻ như đối với @Hidden.

Đối với tôi cách dễ dàng hơn để đạt được nó, là để tạo ra một hộp kiểm và thiết lập hiển thị để "none"

@html.CheckBoxFor(m=> m.HasPreviouslyIssuedCard, new { style ="display:none"})) 

Với giải pháp này, bạn sẽ có một biến gõ hơn trong cả hai ngôn ngữ (C# & JavaScript) .

+0

Điều này dường như không trả lời được câu hỏi đó là lý do tại sao nó hiển thị dưới dạng 'false' đôi khi và' False' những người khác ... – Chris

+0

** False ** => Định dạng chuỗi, ** false ** => Định dạng Boolean. Hộp kiểm sẽ sử dụng tất cả các định dạng Boolean và trong JSCondition bạn có thể không phải so sánh với chuỗi. – OrcusZ

+0

Đó là một giải pháp thú vị nhưng vẫn là giải pháp thay thế. Tôi đang tìm cách giải thích * tại sao * trường hợp thay đổi – DiskJunky

Các vấn đề liên quan