I'm developing an MVC Login application
I wanted to redirect to MainPage URL (Ex:-www.amazon.in) from controller to view once the user is validated successfully
Here my Code
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
var result = await SignInManager.PasswordSignInAsync(model.StoreNumber, model.UserName, model.Password, model.RememberMe, shouldLockout: true);
switch (result)
{
case MolSignInStatus.Success:
return RedirectToLocal(returnUrl);
}
}
private ActionResult RedirectToLocal(string returnUrl)
{
var returnPath = new Uri(returnUrl).AbsolutePath;
if (Url.IsLocalUrl(returnPath))
{
//return Redirect(returnUrl);
return JavaScript("window.location = 'www.amazon.in'");
}
return RedirectToAction("Index", "StoreRegistration");
}
#using (Ajax.BeginForm("Login", "Account", new AjaxOptions { HttpMethod = "POST", OnSuccess = "successOfAddition", OnFailure = "failureOfAddition" }
))
{
}
<script type="text/javascript">
function successOfAddition(data) {
if (data.MessageType == '') {
}
}
function failureOfAddition(data) {
debugger;
showAlert(data.MessageType, data.Message);
}
</script>
Here i want to get the returnUrl value from RedirectToLocal ActionResult method of controller, basically i wanted to redirct the user to new web site on succesfull login.
The below code is not working with Ajax Post
return Redirect(returnUrl);
so I'm trying to use
return JavaScript("window.location = + 'www.amazon.in'");
It works fine but instead of hard coding the url value i wanted it to pass to my view on OnSuccess function.
Related
I would like to have login form as PartialView or ViewComponent. User types username and password I want to login using ajax and show possible validation errors, either using jQuery or rerendering the login form on the server. I don't care.
This seems trivial, but are there any existing samples or templates for login using AJAX? I don't want to reinvent the wheel.
Im starting with default Visual Studio Template for ASP.NET Core Web Application with local accounts where login is separate page. It uses bootstrap. Ideally I would like to stick as close as possible to this.
The login post action looks like this:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginFormViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
_logger.LogInformation(1, "User logged in.");
return RedirectToLocal(returnUrl);
}
if (result.IsLockedOut)
{
_logger.LogWarning(2, "User account locked out.");
return View("Lockout");
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Here is a snippet my code in the account controller for AJAX based login to get you started:
// GET: /Account/LoginAjax
[HttpGet]
[AllowAnonymous]
[RequireHttps]
public IActionResult LoginAjax(string returnUrl = null)
{
if (!_signInManager.IsSignedIn(User))
{
if (Request.Cookies["Identity.External"] != null)
{
// TODO: this is a temp solution, see https://github.com/aspnet/Security/pull/980
// http://stackoverflow.com/questions/38751641/app-redirects-to-account-accessdenied-on-adding-oauth
// when fixed in Microsoft.AspNetCore.Authentication, remove the whole block
Response.Cookies.Delete("Identity.External");
}
}
return PartialView("_LoginPartial", new LoginViewModel { RememberMe = true, ReturnUrl = returnUrl });
}
// POST: /Account/LoginAjax
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
[RequireHttps]
public async Task<IActionResult> LoginAjax(LoginViewModel model, string returnUrl = null)
{
returnObject ret = new returnObject();
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
ret.success = true;
ret.message = "logged-in";
}
else if (result.IsLockedOut)
{
ModelState.AddModelError(string.Empty, "This account has been locked out, please try again later.");
}
else
{
ModelState.AddModelError(string.Empty, "The email address or password supplied are incorrect. Please check your spelling and try again.");
}
}
if (!ret.success) //login was unsuccessful, return model errors
ret.message = ModelErorrs(ModelState);
return Json(ret);
}
public static string ModelErorrs(Microsoft.AspNetCore.Mvc.ModelBinding.ModelStateDictionary modelState)
{
return string.Join("; ", modelState.Values
.SelectMany(x => x.Errors)
.Select(x => x.ErrorMessage));
}
public class returnObject
{
public bool success { get; set; } = false;
public string message { get; set; } = "";
public string action { get; set; } = "";
}
_LoginPartial.chtml:
<form id="formLoginAJAX" asp-controller="Account" asp-action="LoginAjax" asp-route-returnurl="#Model.ReturnUrl" method="post">
......
</form>
Prototype fot client JS:
// dialog form submit handler
$form.submit(function (event) {
event.preventDefault();
if (!$form.valid())
return; // form is not valid
// submit validated form via Ajax
var res = { success: false, message: '' };
$.ajax({
type: 'POST',
dataType: 'json',
url: $form.attr('action'),
xhrFields: {
withCredentials: true
},
data: $form.serializeObject(),
beforeSend: function () {
//disable submit button to prevent double-click
},
success: function (data) {
res = data;
},
error: function (jqXHR, textStatus, errorThrown) {
res.message = 'Request failed: ' + errorThrown;
},
complete: function () {
if (res.success) {
// all good, user is logged-in
// do callbacks if needed
// close dialog
} else {
// no luck, show returned errors (res.message) in the summary (".validation-summary")
}
}
});
});
i work with Ajax.BeginForm
#model Shared.DataContracts.ConfigurationTransports
#using (Ajax.BeginForm("Save", "ConfigurationTransports",
new AjaxOptions
{
HttpMethod = "POST",
InsertionMode = InsertionMode.Replace
}))
{
Html.RenderPartial("~/Views/ConfigurationTransports/ConfigurationPartialContent.cshtml", Model);
}
And my easy form
#model Shared.DataContracts.ConfigurationTransports
#Html.DevExpress().Label(s =>
{
s.Name = "Id";
s.ClientVisible = false;
}).Bind(Model.Id).GetHtml()
#Html.DevExpress().CheckBox(settings =>
{
settings.Name = "checkBoxUseStop";
settings.Properties.ValueUnchecked = 0;
settings.Properties.ValueChecked = 1;
settings.Text = Resources.UseStops;
}).Bind(Model.UseStop).GetHtml()
#Html.DevExpress().Button(settings =>
{
settings.Name = "btnSave";
settings.UseSubmitBehavior = true;
}).GetHtml()
When I click save a post to method Save and parameter ConfigurationTransports is empty without value, but if i load my form i have there values from my send object.
public ActionResult Save(ConfigurationTransports transport)
{
//Some logic method
return View("Index", preprava.GetData());
}
I read a lot of topic on devexpress forum, but i cant find solution.
Do you have any idea?
thx
decorate your Action with [HttpPost] Annotation
[HttpPost]
public ActionResult Save(ConfigurationTransports transport)
{
//Some logic method
return View("Index", preprava.GetData());
}
I have an Ajax form that updates the partial view it's in, but I need it to update a second partial view as well. I'd like to do this without merging them both into one view and updating that.
I think my best bet is to use a regular jQuery Ajax call on the form's onsuccess, but I don't know what parameters to use so I can just call a Controller Action that returns the partial to have it work.
My form is set up with
#using (Ajax.BeginForm("UpdateDateRange",
new { name = Model.Modules[i].Name },
new AjaxOptions { UpdateTargetId = Model.Modules[i].Name.Replace(" ", "_") + "_module" }
))
{ [Input fields] }
In your onSuccessmethod you can make another ajax call.
So for example in your OnSuccessMehtod call "MethodX"...which would do a ajax call and update a div on your page with returned result
var MethodX = function(id)
{
$.get("ActionName?id=" + id, function (result) {
$("#myAnotherdiv").html(result)
}, 'html');
}
In response to ajax call you can send two partial view that you want with this helper:
public static class MvcHelpers
{
public static string RenderPartialView(this Controller controller, string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = controller.ControllerContext.RouteData.GetRequiredString("action");
controller.ViewData.Model = model;
using (var sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
var viewContext = new ViewContext(controller.ControllerContext, viewResult.View, controller.ViewData, controller.TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
}
And in controller:
return Json(new { view1 = this.RenderPartialView(...), view2 = this.RenderPartialView(...) });
and in success you can get two partialView and replace them with old ones:
function success(data)
{
$("someSelectorToSelectPartial1").html(data.view1);
$("someSelectorToSelectPartial2").html(data.view2);
}
I have an #Ajax.BeginForm for my model which has a boolean value (#Html.CheckBoxFor). If this is checked, I want my HttpPost action to redirect to a new page. Otherwise I want it to just continue being an #Ajax.BeginForm and update part of the page.
Here is my HttpPost action (Note: Checkout is the boolean value in my model)
Controller:
[HttpPost]
public ActionResult UpdateModel(BasketModel model)
{
if (model.Checkout)
{
// I want it to redirect to a new page
return RedirectToAction("Checkout");
}
else
{
return PartialView("_Updated");
}
}
You could use JSON and perform the redirect on the client:
[HttpPost]
public ActionResult UpdateModel(BasketModel model)
{
if (model.Checkout)
{
// return to the client the url to redirect to
return Json(new { url = Url.Action("Checkout") });
}
else
{
return PartialView("_Updated");
}
}
and then:
#using (Ajax.BeginForm("UpdateModel", "MyController", new AjaxOptions { OnSuccess = "onSuccess", UpdateTargetId = "foo" }))
{
...
}
and finally:
var onSuccess = function(result) {
if (result.url) {
// if the server returned a JSON object containing an url
// property we redirect the browser to that url
window.location.href = result.url;
}
}
Whats the simplest way of just returning an int from an Ajax MVC Action call?
I am currently trying:
public ContentResult Create(MyModel model)
{
return Content("1");
}
using (Ajax.BeginForm("Create",
new AjaxOptions {
OnComplete = "function(data) { alert(data); }"
}))
I get alert [object Object]. How do I get the int value? Or if possible return the int directly instead of having to use a ContentResult?
I would do something like this:
public JsonResult Create(MyModel model)
{
return Json(new { Result = 1 });
}
using (Ajax.BeginForm("Create",
new AjaxOptions {
OnComplete = "function(data) { alert(data.get_response().get_object().Result); }"
}))