Returning both Partial View and a Message
I have a partialview where it's possible to change a Connection String. When submitting an Edit
action is called. From here I want to either return and re-open the partial view if I want the user to have a second go. If everything went well (or crashing) I want to call my JavaScript function Logout
, that logs the user out and redirect to some startpage.
Both solutions works, just not together. I'm clearly missing some best practice, what should I do?
Partial View: EditSetting
@model WebConsole.ViewModels.Setting.SettingViewModel
@using (Ajax.BeginForm("Edit", "Setting", new AjaxOptions { UpdateTargetId = "div" }, new { id = "editform" }))
{
<fieldset>
@Html.AntiForgeryToken()
<div class="form-horizontal">
@Html.ValidationSummary(true, "", new {@class = "text-danger"})
<div class="form-group">
@Html.LabelFor(model => model.User, htmlAttributes: new {@class = "control-label col-md-2"})
<div class="col-md-10">
@Html.EditorFor(model => model.User, new {htmlAttributes = new {@class = "form-control"}})
@Html.ValidationMessageFor(model => model.User, "", new {@class = "text-danger"})
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.Password, htmlAttributes: new {@class = "control-label col-md-2"})
<div class="col-md-10">
<input type="password" name="Password" id="Password" value=""/>
@Html.ValidationMessageFor(model => model.Password, "", new {@class = "text-danger"})
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.DataSource, htmlAttributes: new {@class = "control-label col-md-2"})
<div class="col-md-10">
@Html.EditorFor(model => model.DataSource, new {htmlAttributes = new {@class = "form-control"}})
@Html.ValidationMessageFor(model => model.DataSource, "", new {@class = "text-danger"})
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.InitialCatalog, htmlAttributes: new {@class = "control-label col-md-2"})
<div class="col-md-10">
@Html.EditorFor(model => model.InitialCatalog, new {htmlAttributes = new {@class = "form-control"}})
@Html.ValidationMessageFor(model => model.InitialCatalog, "", new {@class = "text-danger"})
</div>
</div>
</div>
</fieldset>
}
JavaScript: Submit
$('form').submit(function () {
var $self = $(this);
if ($(this).valid()) {
// Change Connection String
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (message) {
// Use Partial View
//$('#myModal .modal-body').html(message);
// Conn Str is now changed. Log out and redirect
logOut($self, message);
},
error: function (message) {
logOut($self, message);
}
});
}
return false;
});
Action: Edit
[HttpPost]
public ActionResult Edit(SettingViewModel model)
{
// Validate inputs
if (!ModelState.IsValid)
{
ModelState.AddModelError("", @"Not all inputs are valid.");
return PartialView("EditSetting", model);
}
var sql = new DAL.SQL(DAL.SQL.GenerateConnectionString(model.DataSource, model.InitialCatalog, model.User, SecurePassword(model.Password)));
// Validate Connection String
if (!sql.Open())
{
ModelState.AddModelError("", @"Error. Unable to open connection to Database.");
return PartialView("EditSetting", model);
}
// Validate a transaction
if (!sql.IsRunningTransact())
{
ModelState.AddModelError("", @"Error. Unable to connect to Database Server.");
return PartialView("EditSetting", model);
}
// Save Connection String
BuildAndEncryptConnString(model);
return Content("The Connection String is changed. Log in again to continue.");
}
Using the extension method RenderToString and basead on cacois answer, you can create your action like this:
public ActionResult Edit(SettingViewModel model)
{
// "Ifs" to return only partials
if (ModelState.IsValid)
{
return PartialView("EditSetting", model);
}
...
// Returning a Json with status (success, error, etc), message, and the content of
// your ajax, in your case will be a PartialView in string
return Json(new {
Status = 1,
Message = "error message",
AjaxReturn = PartialView("EditSetting", model).RenderToString()});
}
Ps. I suggest you to create a model to define the Ajax return, with Status
, Message
and AjaxReturn
. With that, your ajax requests will always return the same object type. For the Status
property you can create a Enum.
Your ajax request, will be like this:
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (data) {
if(data.Message == undefined) {
// Use data like a partial
} else {
// Use data.Message for the message and data.AjaxReturn for the partial
}
},
error: function (message) {
logOut($self, message);
}
});
Add error handling to your ViewModel:
bool hasErrors;
string errorMessage;
In your controller, if the data validation is ok, just return the PartialView or return RedirectToAction("Index");
. If not, set hasErros = true;
and a custom errorMessage
.
In the view, place an error block someone where the user will see it:
@if (Model.hasErrors)
{
<div>Model.errorMessage</div>
}
By the way, you can do the data validation inside the ViewModel constructor.
You can Return the Patial View, and Intialize ViewBag and assign the message to it, then in the view check if have value and show it if true.
Controller:
[HttpPost]
public ActionResult Edit(SettingViewModel model)
{
// Put the ViewBag where ever you want
ViewBag.ErrorMsg =" Error";
return PartialView("EditSetting", model);
}
View:
@if(ViewBag.ErrorMsg !=null )
{
<div>@ViewBag.ErrorMsg</div>
}
I hope that helped.
链接地址: http://www.djcxy.com/p/42106.html上一篇: 查询字符串的最大可能长度是多少?
下一篇: 返回部分视图和消息