2017-10-21 68 views
0

我有一個與名稱,電子郵件和電話的簡單聯繫表格的視圖。我在同一個父頁面上重複使用這個表單兩到三次。當用戶提交其中一個表單時,我檢測到提交的表單並使用Dapper通過javascript/jQuery將內容發佈到數據庫。如何在相同的MVC頁面上使用相同的模型重用表單?

問題是,當我在任何頁面上重新使用聯繫表單時,輸入字段將不會生成唯一的ID。這會導致w3驗證失敗,說Duplicate ID。在這種特殊情況下,我需要頁面通過w3驗證。

我該如何解決這個問題?我嘗試使用ViewData.TemplateInfo.HtmlFieldPrefix來爲輸入字段添加前綴,但由於前綴值是靜態的,因此不能真正解決問題。如果我做了一個隨機前綴值,那麼我怎樣才能捕獲到HttpPost控制器?

這是我的代碼。

Index.cshtml - 有幾次提到ContactForm.cshtml

<html> 
<head>...</head> 
<body> 
.... 
@{Html.RenderAction("ContactForm")} 
.... 
@{Html.RenderAction("ContactForm")} 
.... 
</body> 
</html> 

ContactForm.cshtml

@model ProjectX.Models.CaseModel 
@using (Html.BeginForm("SendMessage", "Home", FormMethod.Post)) 
{ 
    @Html.TextInputFor(model => model.Name, Res.Name, new { placeholder = Res.Name }) 
    @Html.TextInputFor(model => model.Phone, Res.Phone, new { placeholder = Res.Phone, type = "tel" }) 
    @Html.TextInputFor(model => model.Email, Res.Email, new { placeholder = Res.Email, type = "email" }) 
    <input type="submit" value="Send" onclick="jsSaveForm(event);" /> 
} 

// @Html.TextInputFor MvcHtmlString helper method 
public static MvcHtmlString TextInputFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, string title, Object htmlAttributes = null) 
{ 
    var req = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).IsRequired; 
    var name = helper.ViewData.TemplateInfo.GetFullHtmlFieldId(ExpressionHelper.GetExpressionText(expression)); 
    if (req) 
     title += " *"; 

    string html = String.Format("<div class=\"inp\"><label for=\"{2}\">{0}</label>{1}</div>", helper.ValidationMessageFor(expression), helper.TextBoxFor(expression, htmlAttributes), name); 
    return new MvcHtmlString(html); 
} 

CaseModel.cs

public class CaseModel 
{ 
    [Required(ErrorMessageResourceType = typeof(Res), ErrorMessageResourceName = "ValidationRequired")] 
    public string Name { get; set; } 
    public string Phone { get; set; } 
    public string Email { get; set; } 
} 

的HomeController

// GET 
[ChildActionOnly] 
[Route("~/Home/ContactForm")] 
public ActionResult ContactForm() 
{ 
    // tried this but this is a static value. 
    // ViewData.TemplateInfo.HtmlFieldPrefix = "SomePrefix"; 

    return PartialView(new CaseModel()); 
} 

// POST 
[HttpPost] 
[Route("~/Home/SendMessage")] 
public async Task<PartialViewResult> SendMessage(CaseModel model) 
{ 
    ... brevity... 
    await SaveData(model); 
} 
+0

爲什麼您需要前綴?您是否要在同一頁面上多次插入表單? – Shyju

+0

您可以隨時刪除'id'屬性 - 'new {id =「」,placeholder = Res.Name}' –

+0

@Shyju - 也許我不需要前綴,但如果在頁面上出現兩次相同的ID,w3驗證將失敗,並且在這種情況下肯定不會。另外,我還會執行一些jquery客戶端驗證 - 例如字段爲空等 – Sha

回答

1

您只需將其設置爲在htmlAttributes參數爲空字符串中刪除id屬性,例如

@Html.TextInputFor(model => model.Name, Res.Name, new { id = "", placeholder = Res.Name }) 

雖然你可能要考慮這樣做在您的TextInputFor()擴展方法。

作爲一個側面說明,你的擴展使用[Display(Name = "...")]屬性時,和title參數是不必要的方法沒有考慮到的顯示名稱的屬性(我建議你的代碼應該是

public static MvcHtmlString TextInputFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes = null) 
{ 
    ModelMetadata metaData = ModelMetadata.FromLambdaExpression(expression, helper.ViewData); 
    string displayName = metaData.DisplayName; 
    if (metaData.IsRequired) 
    { 
     displayName += " *"; 
    } 
    StringBuilder html = new StringBuilder(); 
    html.Append(helper.LabelFor(expression, displayName).ToString()); 
    html.Append(helper.TextBoxFor(expression, htmlAttributes).ToString()); 
    html.Append(helper.ValidationMessageFor(expression).ToString()); 
    TagBuilder container = new TagBuilder("div"); 
    container.AddCssClass("inp"); 
    container.InnerHtml = html.ToString(); 
    return new MvcHtmlString(container.ToString()); 
} 
+0

非常感謝!:)出於好奇,如果實際上需要'id's'是唯一的 - 這怎麼能實現呢? – Sha

+0

擁有'id'屬性的唯一原因是在css或javascript/jQuery選擇器中使用,所以在你的情況下你可能不需要它們,但是有一些選擇,例如創建一個'Guid'並將其附加到由助手生成的'id'(但是這會使得它們在css或javascript選擇器方面無用) –

+0

作爲一個附註,你的擴展方法中也有一個關於標籤的缺陷 - 它不會使用任何值'[Display(Name =「...」)]'你可能會應用到你的屬性的屬性。你方法中的第二個參數似乎毫無意義。當我有機會的時候,我會更新你的擴展方法應該看起來如何的答案,包括如何去除幫助器本身中的'id'屬性 –

相關問題