Model mit Ajax-Formular
-
21-08-2019 - |
Frage
Ich verwende ein AJAX Formular ein Element in die Datenbank zu aktualisieren. Wenn es getan wird, gibt es eine Teilansicht, die die Elemente alle neu Listen und zeigt sie alle in einer Tabelle. Das Problem tritt auf, wenn ich einen Model Fehler in meiner Controller-Aktion hinzuzufügen habe. Ich will nicht die Liste der Elemente zurück, wenn es ein Fehler Model ist, weil ich den Benutzer der Fehler mit der Validation zeigen will. Mein Denken ist, dass ich so etwas in meinem Controller tun könnte:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult UpdateNewsItem(int newsID, string newsTitle, string newsDescription, string newsBeginningDate, string newsEndingDate)
{
List<Models.News> lstNewsItem = new List<News>();
//we need to grab the member so we can capture the user id
//for the corresponding news property
MembershipUser member = Membership.GetUser(User.Identity.Name);
//the news instance to use in case the viewdata is invalid
Models.News newsError = new Models.News();
//create the datetime objects
DateTime dtBeginningDate = DateTime.MinValue;
DateTime dtEndingDate = DateTime.MaxValue;
//the message we want to send whenever the user enters an invalid date
string strInvalidDateError = "Invalid date. Please use a format like '12/25/2008'";
//clean user input
newsTitle = Models.clsGlobals.CleanString(newsTitle);
newsDescription = Models.clsGlobals.CleanParagraph(newsDescription);
//newsTitle
if (string.IsNullOrEmpty(newsTitle))
{
newsError.Title = string.Empty;
ModelState.AddModelError("newsTitle", "You must enter a news title.");
}
//description
if (string.IsNullOrEmpty(newsDescription))
{
newsError.Description = string.Empty;
ModelState.AddModelError("newsDescription", "You must enter a news description.");
}
//beginningDate
if (string.IsNullOrEmpty(newsBeginningDate))
{
ModelState.AddModelError("newsBeginningDate", "You must enter a beginning date.");
}
//endingDate
if (string.IsNullOrEmpty(newsEndingDate))
{
ModelState.AddModelError("newsEndingDate", "You must enter an ending date.");
}
//set the beginning date
try
{
dtBeginningDate = DateTime.Parse(newsBeginningDate);
newsError.BeginningDate = dtBeginningDate;
}
catch (FormatException)
{
ModelState.AddModelError("newsBeginningDate", strInvalidDateError);
}
//set the ending date
try
{
dtEndingDate = DateTime.Parse(newsEndingDate);
newsError.EndingDate = dtEndingDate;
}
catch (FormatException)
{
ModelState.AddModelError("newsEndingDate", strInvalidDateError);
}
//data is validated, so we can begin the update
if (ModelState.IsValid == true)
{
try
{
//use to perform actions on db
Models.NewsDataContext dcNews = new Models.NewsDataContext();
//fetch the items that match what the user requested to edit
lstNewsItem = this.GetNewsItem(newsID);
//set news properties
foreach (Models.News news in lstNewsItem)
{
news.UserId = (Guid)member.ProviderUserKey;
news.Title = newsTitle;
news.Description = newsDescription;
news.EntryDate = DateTime.Now;
news.BeginningDate = dtBeginningDate;
news.EndingDate = dtEndingDate;
}//next
//update the transaction
dcNews.SubmitChanges();
//update the news list
return PartialView("NewsList", this.GetNewsItems());
}
//just to make sure everything goes as planned,
// catch any unhandled exceptions
catch (Exception ex)
{
ModelState.AddModelError("_FORM", ex);
}//end catch
}//end if valid modelstate
//invalid modelstate, so repopulate the viewdata and
//send it back
//the list to hold the entries
List<Models.News> lstErrorNewsItems = new List<Models.News>();
//set the remaining error properties
newsError.UserId = (Guid)member.ProviderUserKey;
newsError.NewsID = newsID;
newsError.EntryDate = DateTime.Now;
//add the item--there will only be one
//but the view is expecting a list so we will
//treat it like one
lstErrorNewsItems.Add(newsError);
return PartialView("EditNews", lstErrorNewsItems);
}//end actionresult
Das Problem ist, dass, wenn ein Model Fehler auftritt, das Model Bildschirmtextsystem nicht zurückgegeben wird. Ich vermute, es ist möglich, weil ich kein Update Zielkennummer angeben. Aber ich kann nicht einen anderen updatetargetid gesetzt, weil ich bereits eine haben. Irgendwelche Ideen?
Lösung 2
In Ordnung, ich habe es herausgefunden. Danke für die Antwort. Für die Zukunft, was ich tun musste, war ein Hauptteiler eingerichtet, die alle meine Inhalte in geht. Dann stelle ich stets die updateTargetID zu diesem Teiler, so dass es keine Rolle, welche Inhalte es zeigt, nur, dass es es anzeigt. Damit wird eigentlich aus leichter sein, weil Sie Funktionen Javascript nicht verschwenden müssen andere div-Tags Einstellung auf und ab, weil Sie nur eine verwenden, die ständig aktualisiert wird.
Andere Tipps
if (!Model.IsValid) {
return PartialView("YourEditForm");
}
else
{
return View("YourIndexView");
}
Sollte für erneute Anzeigen Ihre Bearbeitungsformular mit Validierungsfehler und alle gut funktionieren. Viewdata wird von Post Daten gefüllt.
Großes Update
Ich habe einige Tests gemacht, um es herauszufinden. Und kam mit einem Arbeitstestprojekt auf. hier sind einige Einträge:
Mein Testing Controller
public class TestController : Controller
{
//
// GET: /Test/
List<TestData> data;
public TestController()
{
data = new List<TestData>();
for (var i = 0; i < 10; i++)
{
data.Add(new TestData(){Name=string.Format("TestData{0}",i.ToString().PadLeft(4,'0'))});
}
}
public ActionResult Index()
{
return View( data);
}
public ActionResult Edit(string name)
{
if (Request.IsAjaxRequest())
{
return PartialView("AjaxEdit", new TestData() { Name = name });
}
return View(new TestData() { Name = name });
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(TestData testData)
{
ModelState.AddModelError("name", "incorrect name");
if (!ModelState.IsValid)
{
if (Request.IsAjaxRequest())
{
return PartialView("AjaxEdit");
}
}
return View();
}
}
Meine Ansicht bearbeiten:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<AjaxValidationPartial.Models.TestData>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Edit
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Edit</h2>
<div id="editForm">
<% Html.RenderPartial("AjaxEdit",Model );%>
</div>
</asp:Content>
Meine Ajax Partial Ansicht bearbeiten
"%>
<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again.") %>
<% using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "editForm" }))
{%>
<fieldset>
<legend>Fields</legend>
<p>
<label for="Name">Name:</label>
<%= Html.TextBox("Name")%>
<%= Html.ValidationMessage("Name", "*")%>
</p>
<p>
<input type="submit" value="Save" />
</p>
</fieldset>
<% } %>
<div>
<%=Html.ActionLink("Back to List", "Index") %>
</div>
Und meine Testdata Modellklasse
public class TestData
{
public string Name { get; set; }
}
Mit diesem Code funktioniert es nur, wie man wollte. Hinweis, dass ich in meiner „Post“ Aktion bearbeiten kein Modell zu Teilansicht passieren. Ansicht, die gerendert wird, wird auch alle Werte, die sie von einer Post-Anforderung benötigt.