AJAX Model Validation with Partial View - ajax

I have a partial view, which is a login that functions as a popup. All I want to do is have my model do the validation (server side) and return any errors via AJAX. The code below returns the partial view only with the errors. I want my action result to not return a a view, but only the errors. In old ASP.NET, this would be a Partial Post back. I am not sure how to accomplish this in MVC.
Here is the Model
public class LoginModel
{
[Required]
public String Email { get; set; }
[Required]
[DataType(DataType.Password)]
public String Password { get; set; }
}
Here is the Partial View
#model MySite.Models.LoginModel
#using (Ajax.BeginForm("Authenticate", "Account", null, new AjaxOptions { OnFailure = "error" }, new { id = "LoginForm" }))
{
<div class="modal-body" id="LoginPopupDialogMessage">
The page you have requested requires you to login. Please enter your credentials and choose your country:
<br />
<br />
<div class="row">
<div class="form-group col-lg-offset-2 col-lg-8">
<label>Email Address</label>
#Html.TextBoxFor(u => u.Email, new { #class = "form-control input-lg input-sm", id = "Email", name = "Email" })
#Html.ValidationMessageFor(u => u.Email)
</div>
</div>
<div class="row">
<div class="form-group col-lg-offset-2 col-lg-8 ">
<label>Password</label>
#Html.PasswordFor(u => u.Password, new { #class = "form-control input-lg input-sm", name = "Password" })
#Html.ValidationMessageFor(u => u.Password)
</div>
</div>
<div style="text-align: center; padding-top: 20px;" class="ImageGroup">
<button name="companyCode" value="LB_US" class="btn-link" type="submit">
<img src="../../WebContent/Images/icon-flag-usa.png" />
</button>
<button name="companyCode" value="LB_CA" class="btn-link" type="submit">
<img src="../../WebContent/Images/icon-flag-canada.png" />
</button>
<button name="companyCode" value="LB_EU" class="btn-link" type="submit">
<img src="../../WebContent/Images/icon-flag-europe.png" />
</button>
</div>
</div>
}
I call the parial view from _layout.cshtml.
<div class="modal fade" id="LoginPopupDialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel1" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header" style="background: #e7e3e7; color:#000;">
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="color:#000;">
<span aria-hidden="true">×</span>
</button>
<div class="modal-title" id="LoginPopupDialogHeader">Please Login</div>
</div>
#Html.Action("Login", "Account")
</div>
</div>
</div>
My Controller Action:
[HttpPost]
[Route("account/authenticate")]
public ActionResult Authenticate(String companyCode, LoginModel model)
{
if (!ModelState.IsValid)
{
// ??
}
return PartialView("Login", model);
}

Since your code is doing an ajax form submission for the login, you should try to return a JSON response from the server. If model validation fails, you may read the validation errors from the model state dictionary and store that in a collection of strings (error messages) and return that as part of the json response. If model validation passes, you can continue executing your code to verify the login credentials and if those looks good, send back a json response with the next url for the user (to which we can redirect the user).
[HttpPost]
public ActionResult Authenticate(String companyCode, LoginModel model)
{
if (!ModelState.IsValid)
{
var errors = ViewData.ModelState.Values
.SelectMany(x => x.Errors.Select(c => c.ErrorMessage));
return Json(new { Status = "Error", Errors = errors });
}
//to do :Verify login, if good, return the below respose
var url=new UrlHelper(Request.RequestContext);
var newUrl = url.Action("About");
return Json(new { Status="Success", Url = newUrl});
}
Now in your view, you may specify a OnSuccess handler as part of the AjaxOptions. This will be a javascript object to which the json response from the server will come. We basicallly need to check the Status property value and do the appropriate things.
new AjaxOptions { OnFailure = "error" , OnSuccess="loginDone"}
The below implementation of loginDone simply alerts the error messages. You can update it to show it as part of the DOM.
function loginDone(d) {
if (d.Status === "Success") {
window.location.href = d.Url;
} else {
$.each(d.Errors,function(a, b) {
alert(b);
});
}
}
You may also consider enabling the unobtrusive client side validation which does the client side validation before trying to make a call to server. This will also show the error messages in the validation error spans (same as the normal mvc model validation does)

Related

ModelState.AddModelError for Ajax loaded partials

I have a partial view on my main page that loads a form, the model is below:
public class CreateRequestViewModel
{
[Required]
public short ClientId { get; set; }
[Required]
public Guid SystemId { get; set; }
[Required]
public string RequestedUsername { get; set; }
public string TicketReference { get; set; }
public string Notes { get; set; }
public List<SelectListItem> Clients { get; set; }
public List<SelectListItem> Systems { get; set; }
}
This is the partial view:
#model Models.CreateRequestViewModel
#Html.AntiForgeryToken()
#Html.ValidationSummary(true, "", new { #class = "text-danger" })
<div class="row">
<div class="col-lg-4 col-md-4 col-sm-12">
<h1>Create a Request</h1>
</div>
<div class="col-lg-8 col-md-8 col-sm-12 right">
<div class="form-group">
#Html.DropDownListFor(m => m.ClientId, Model.Clients, htmlAttributes: new { #class = "form-control form-control-lg", #id = "ClientSelect" })
#Html.ValidationMessageFor(m => m.ClientId, "", htmlAttributes: new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.DropDownListFor(m => m.SystemId, Model.Systems, htmlAttributes: new { #class = "form-control form-control-lg", #id = "ClientSystemSelect" })
#Html.ValidationMessageFor(m => m.SystemId, "", htmlAttributes: new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.TextBoxFor(m => m.RequestedUsername, htmlAttributes: new { #class = "form-control form-control-lg", #placeholder = "Username" })
#Html.ValidationMessageFor(m => m.RequestedUsername, "", htmlAttributes: new { #class = "text-danger" })
</div>
<div class="form-group">
#Html.TextBoxFor(m => m.TicketReference, htmlAttributes: new { #class = "form-control form-control-lg", #placeholder = "Ticket reference" })
</div>
<div class="form-group">
#Html.TextAreaFor(m => m.Notes, htmlAttributes: new { #class = "form-control form-control-lg", #rows = 3, #placeholder = "Notes..." })
</div>
<input type="Submit" class="btn btn-secondary btn-block send-request" value="Submit" name="">
</div>
</div>
This is how I'm loading the page:
<div class="container">
<div class="row">
<div class="col-lg-6">
<form asp-action="CreateRequest" asp-controller="Access"
data-ajax="true"
data-ajax-method="POST"
data-ajax-mode="replace"
data-ajax-update="#createRequest">
<div id="createRequest">
#await Html.PartialAsync("_CreateRequest", Model.CreateRequestModel)
</div>
</form>
</div>
</div>
</div>
With the model as it is and using the unobtrusive javascript, leaving the RequestedUsername blank for example will result in the form not being submitted and a validation message appearing for it. This is great.
However, I have a requirement to check the form data against entries in a database first and throw an error if there's an existing record. I thought that, with all the client side validation passing, I'd use ModelState.AddModelError in the controller like so:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult CreateRequest(CreateRequestViewModel model)
{
if(model.RequestedUsername == "someincorrectvalue"){ //actual logic removed for brevity
ModelState.AddModelError("RequestedUsername", "Already in use");
}
if(!ModelState.IsValid)
{
//reset lists on model, removed
return PartialView("_CreateRequest", model);
}
_logger.LogInformation("CreateRequest successful");
return RedirectToAction(nameof(Index));
}
However, if I use ModelState.AddModelError, the return PartialView("_CreateRequest", model) call ends up reloading the whole page as if it's returning a full View.
I'm at a loss as to why this is happening. The difference I can see is that i'm adding a ModelState error inside the controller, whereas validation is happening client side otherwise.
Anyone have an idea?
So, this turned out to be a combination of problems. To begin with, the unobtrusive Ajax scripts I had within my solution were not performing. I don't know why but I replaced them with one from the CDN: https://ajax.aspnetcdn.com/ajax/jquery.unobtrusive-ajax/3.2.5/jquery.unobtrusive-ajax.min.js
That solved the problem of the whole page reloading instead of the partial being returned via unobtrusive ajax.
The second problem was that, on success, I was redirecting to the Index controller action instead of returning a Partial again. This was causing the entire Index page to be rendered inside the div i'd chosen as my ajax target. My controller action now looks like this:
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult CreateRequest(CreateRequestViewModel model)
{
if(model.RequestedUsername == "someincorrectvalue"){ //actual logic removed for brevity
ModelState.AddModelError("RequestedUsername", "Already in use");
}
if(!ModelState.IsValid)
{
//reset lists on model, removed
return PartialView("_CreateRequest", model);
}
_logger.LogInformation("CreateRequest successful");
// reset lists on model, removed
ModelState.Clear(); // get rid ofany model details to make way for a new request
return PartialView("_CreateRequest", model);
}

ASP Core Ajax Posting From Partials

I have a requirement to separate parts of one page into Partial Views and one of those parts contains a form to submit data. I've been playing around with this and have managed to get the form to submit without reloading the page.
However I have two problems:
The form fields don't clear after a successful post
If validation is broken, those validation messages don't appear when returning the result.
I'll admit i'm not too familiar with AJAX in ASP to begin with but hopefully someone can hope. Here's my code:
Model
using System.ComponentModel.DataAnnotations;
namespace MVCValidation.Models
{
public class Thing
{
public int Id { get; set; }
[Required]
public string Value { get; set; }
public string OtherValue { get; set; }
}
}
Main View (_Index.cshtml)
#model MVCValidation.Models.Thing
#{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Ajax Partial Test</h1>
</div>
<div class="row">
<div class="col">
<form asp-controller="Home" asp-action="Edit" data-ajax="true" data-ajax-method="POST">
#await Html.PartialAsync("_Form", Model)
</form>
</div>
</div>
Partial View (_Form.cshtml)
#model MVCValidation.Models.Thing
#Html.AntiForgeryToken()
<div class="form-horizontal">
#Html.ValidationSummary(true, "", new {#class = "text-danger"})
#Html.HiddenFor(m => m.Id)
<div class="form-group">
#Html.LabelFor(m => m.Value, htmlAttributes: new { #class = "control-label col-md-2" })
<div class="col-md-10">
#Html.EditorFor(m => m.Value, new {htmlAttributes = new { #class = "form-control" }})
#Html.ValidationMessageFor(m => m.Value, "", new { #class = "text-danger" })
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" value="submit" class="btn btn-success"/>
</div>
</div>
</div>
Controller (HomeController)
namespace MVCValidation.Controllers
{
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
public Thing GetThing()
{
return new Thing(){Id = 1, OtherValue = "Other"};
}
public IActionResult Index()
{
return View(GetThing());
}
[ValidateAntiForgeryToken]
[HttpPost]
public IActionResult Edit(Thing thing)
{
if(ModelState.IsValid)
{
ModelState.Clear();
return PartialView("_Form", GetThing());
}
return PartialView("_Form", thing);
}
}
}
In my _Layout view I have the jquery.unobtrusive-ajax.min.js referenced and it's loading fine. Please can anyone suggest where I'm going wrong?
So, I eventually found this article: https://damienbod.com/2018/11/09/asp-net-core-mvc-ajax-form-requests-using-jquery-unobtrusive/ and saw what I was doing wrong.
I expanded my tag to look like below:
<form asp-controller="Home" asp-action="Edit"
data-ajax="true"
data-ajax-method="POST"
data-ajax-mode="replace"
data-ajax-update="#result">
<div id="result">
#await Html.PartialAsync("_Form", Model)
</div>
</form>
the PartialAsync call now takes place inside a div that ultimately will be the target for the result to populate... so it effectively replaces itself.
I also had to change the controller method to this:
[ValidateAntiForgeryToken]
[HttpPost]
public IActionResult Edit(Thing thing)
{
if(ModelState.IsValid)
{
return RedirectToAction(nameof(Index));
}
return PartialView("_Form", thing);
}
This correctly returns the partial view when the model is invalid, and allows the page to be used again if it is valid.

How do you connect a POST to a different razor page loaded via AJAX into a modal popup?

Edit: Have marked up where the error in the original code was stopping this from working.
I can find plenty of info and examples of this on MVC, but doesn't seem to apply for Razor Pages?
Simple scenario: I have a page (FooList) showing a list of Foo items. Each has an Edit button. This opens a modal popup with the layout (and data) coming from a second page (FooEdit).
The Edit form appears and populates fine, but I can't work out how to get it to post the data back to the FooEdit code behind?
List page, FooList.cshtml
#page
#model Pages.FooListModel
<table>
#foreach (var item in Model.FooListVM)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.Name)
</td>
<td>
<a onclick="openModal(#item.ID);">Edit</a>
</td>
</tr>
}
</table>
<div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header border-bottom-0">
<h5 class="modal-title" id="exampleModalLabel">Edit Foo</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<form> <---- Edit: ** This shouldn't be here **
<div class="modal-body">
</div>
</form> <---- Edit
</div>
</div>
</div>
<script>
function openModal(i) {
$.get("FooEdit?id="+i,
null,
data => {
$("#editModal").modal("show");
$("#editModal .modal-body").html(data);
});
};
</script>
Code behind, FooList.cshtml.cs
public class FooListModel : PageModel
{
public IList<FooListVM> FooListVM { get; set; }
public void OnGet()
{
FooListVM = new List<FooListVM>
{
new FooListVM { ID = 1, Name = "Foo 1" },
new FooListVM { ID = 2, Name = "Foo2" }
};
}
}
public class FooListVM
{
public int ID { get; set; }
public string Name { get; set; }
}
Second page for the popup, FooEdit.cshtml
#page
#model Pages.FooEditModel
#(Layout=null)
<form method="post">
<input asp-for="FooEditVM.Name" class="form-control" /><br />
<input asp-for="FooEditVM.Stuff1" class="form-control" /><br />
<input asp-for="FooEditVM.Stuff2" class="form-control" /><br />
<input type="submit" value="Save"/>
</form>
And the code behind for the popup, FooEdit.cshtml.cs
public class FooEditModel : PageModel
{
[BindProperty]
public FooEditVM FooEditVM { get; set; }
public void OnGet(int id)
{
FooEditVM = new FooEditVM
{
Name = $"This is item {id}",
Stuff1 = "Stuff1",
Stuff2 = "Stuff2"
};
}
public void OnPost(int id)
{
// How do we get to here???
var a = FooEditVM.Name;
}
}
public class FooEditVM
{
public string Name { get; set; }
public string Stuff1 { get; set; }
public string Stuff2 { get; set; }
}
I've been through all the MS Tutorial stuff on Asp.net Core 2.2, but it doesn't seem to cover this.
Also as a side question, although it works, is there a "ASP helper tag" way of doing the ajax bit?
Have realised the problem was the 'form' tag in the Modal Dialog markup that was clashing the 'form' tag from the partial page. Removing it fixed everything using:
In FooEdit.cshtml
<form id="editForm" asp-page="FooEdit">
. . .
</form>
In FooEdit.cshtml.cs
public void OnPost()
{
// Fires in here
}
I'm pretty sure the fooedit page is going to need some jQuery to handle this.
See below for what I would do in the fooedit page.
#page
#model Pages.FooEditModel
#(Layout=null)
<form id=fooedit method="post" action="FooEdit">
<input asp-for="FooEditVM.Name" class="form-control" /><br />
<input asp-for="FooEditVM.Stuff1" class="form-control" /><br />
<input asp-for="FooEditVM.Stuff2" class="form-control" /><br />
<input type="submit" value="Save"/>
</form>
<SCRIPT language="JavaScript" type="text/Javascript">
<!--
$(document).ready(function(e) {
$("#fooedit").submit(function(e) {
e.preventDefault();
var form_data = $(this).serialize();
var form_url = $(this).attr("action");
var form_method = $(this).attr("method").toUpperCase();
$.ajax({
url: form_url,
type: form_method,
data: form_data,
cache: false,
success: function(returnhtml){
$("#editModal.modal-body").html(returnhtml);
}
});
});
});
</SCRIPT>

Validation error message not displayed in Asp.Net Core 2 MVC partial view

I have an index page with a list of "workbooks" titles and for each workbook, there is a "share" button. When pressing the button a bootstrap model (i.e. dialog) appears which displays the title of the workbook and a textarea allowing the user to type in a sharees email addresses.
When the user presses on the "share" button, I am calling a javascript function which calls a controller action that returns a partial view containing the modal dialog with a form inside it. The problem is that after pressing the submit button (i.e. "Share") there are no validation errors being shown to the user and I am not sure why that is. Could anyone provide some ideas, please?
That is my main (index.cshtml) page:
#model DNAAnalysisCore.Models.WorkBookModel
#{
}
#section BodyFill
{
<script type="text/javascript">
function showSharingView(title) {
var url = "#Url.Action("ShowShareDialog", "Home")" + "?workbookTitle=" + encodeURI(title);
$('#shareFormContainer').load(url,
function() {
$('#shareFormModal').modal("show");
});
}
function hideSharingView() {
$('#shareFormModal').modal("hide");
}
</script>
<div id="shareFormContainer" >
<!--PLACEHOLDER FOR SHARE DIALOG -->
</div>
<div class="workbook-container">
<table class="table">
<tbody>
#foreach (var workbook in Model.Workbooks)
{
<tr>
<td>#Html.ActionLink(workbook.Name, "Open", "OpenAnalytics", new {id = Model.Id, workbook = workbook.Name})</td>
<td>
<button title="Share" class="share-button" onclick='showSharingView("#workbook.Name")'> </button>
</td>
</tr>
}
</tbody>
</table>
</div>
}
That is my Controller:
public class HomeController : Controller
{
[HttpGet]
public IActionResult ShowShareDialog(string workbookTitle)
{
var shareModel = new ShareModel
{
Title = workbookTitle
};
return PartialView("_ShareView", shareModel);
}
[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult ShareWorkbook(string emails, string title)
{
var share = new ShareModel
{
Emails = emails
};
// TODO EMAIL THE SHARED WORKBOOK using the 'title' of the workbook and the 'email' string value
// return no content to avoid page refresh
return NoContent();
}
}
This is my partial view/modal dialog (_ShareView):
#using DNAAnalysisCore.Resources
#model DNAAnalysisCore.Models.ShareModel
<!-- Modal -->
<div class="modal fade" id="shareFormModal" role="dialog">
<div class="modal-dialog modal-md">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Share Workbook - #Model.Title</h4>
</div>
#using (Html.BeginForm("ShareWorkbook", "Home", FormMethod.Post))
{
<div class="modal-body">
<label>#BaseLanguage.Share_workbook_Instruction_text</label>
<div class="form-group">
<textarea class="form-control" asp-for="Emails" rows="4" cols="50" placeholder="#BaseLanguage.ShareDialogPlaceholder"></textarea>
#* TODO add client-side validation using jquery.validate.unobtrusive.js. See US268276 *#
<span asp-validation-for="Emails" class="text-danger"></span>
</div>
<input asp-for="Title" />
</div>
<div class="modal-footer">
<button type="submit" onclick="hideSharingView()" class="btn btn-primary">Share</button>
<button id="btnCancelDialog" type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
</div>
}
</div>
</div>
</div>
#section Scripts {
#{ await Html.RenderPartialAsync("_ValidationScriptsPartial"); }
}
This is my ShareModel:
public class ShareModel
{
[HiddenInput]
public string Title { get; set; }
[Required]
public string Emails { get; set; }
}
The form is not added to the page when the page loads, the unobtrusive validation will not pick it up.A simple solution is to use $.validator.unobtrusive.parse("#id-of-the-form");.Refer to here.
1.Add id to your form in _ShareView partial view:
#using (Html.BeginForm("ShareWorkbook", "Home", FormMethod.Post,new { #id="partialform"}))
2.Introduce validation file _ValidationScriptsPartial.cshtml into main page(Index.cshtml) and manually register the form with the unobtrusive validation.
#section Scripts
{
#await Html.PartialAsync("_ValidationScriptsPartial")
<script type="text/javascript">
function showSharingView(title) {
var url = "#Url.Action("ShowShareDialog", "Home")" + "?workbookTitle=" + encodeURI(title);
$('#shareFormContainer').load(url,
function() {
$('#shareFormModal').modal("show");
$.validator.unobtrusive.parse("#partialform");
});
}
function hideSharingView() {
$('#shareFormModal').modal("hide");
}
</script>
}

Passing Model Data to a Bootstrap Modal on click

I'm extremely new to MVC and I don't know how to make this work-
I have a model that stores different news items based on categories:
NewsModel.cs:
public class NewsModel
{
public int ID { get; set; }
public string category { get; set; }
public String headline { get; set; }
public string source { get; set; }
public DateTime date { get; set; }
public string body { get; set; }
public string summary { get; set; }
}
I have a View that displays each of the news items as a list Item:
Sports.cshtml:
#model IEnumerable<Test.Models.NewsModel>
#foreach (var item in Model)
{
<div class="news_target-left floatleft">
<div class="image-container">
<img src="~/Content/Images/demo_img.png" alt="website template image">
<div class="top-left-text">
#item.category
</div>
</div>
<h3>#item.headline</h3>
<p> #item.summary </p>
<p class="single_cat_left_content_meta"><span>#item.source</span> | #item.date</p>
<span class="readmore">#Html.ActionLink("Read More", "NewsModal", "Home", #item)</span>
</div>
}
When the user clicks on Read More, I want to load a bootstrap modal that gets the current model object and displays the entire news data in detail. Currently, the readmore span uses an Html actionlink that does not seem to be working. I want to load the modal using Ajax but cannot figure out how to do so.
This is the bootstrap Modal that I have:
NewsModal.cshtml:
#model Test.Models.NewsModel
<div id="newsModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Leadsquared Express</h4>
</div>
<div class="modal-body">
<h2>#Model.headline</h2>
<i><small>#Model.source</small></i>
<p>#Model.body</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
The Model is in Models/NewsModel
The Sports View is in Views/Categories/
The Sports controller Action is in Controllers/Categories:Sports
The NewsModal is currently in Views/Categories/. I have tried putting this view in Shared, as well as its own folder, but I'm obviously doing something wrong.
Any help?
Edit:
I used this link to make the following changes but clicking on "Read more" does not open the modal popup.
http://www.c-sharpcorner.com/UploadFile/092589/implementing-modal-pop-up-in-mvc-application/
changed <span class="readmore">#Html.ActionLink("Read More", "NewsModal", "Home", #item)</span> in Sports.cshtml to
<a id="openmodal "href="javascript:void(0)" class="readmore" data-model="#Json.Encode(#item)">Read More</a>
and added this script:
$(document).ready(function () {
var url = "/Home/NewsModal";
var model = $("#openmodal").attr("data-model");
alert("script running- sports.html");
$.ajax({
type: 'GET',
url: '/Home/NewsModal',
data: model,
contentType: 'application/json; charset=utf-8',
success: function (data, status, settings) {
$("#openmodal").html(data);
},
error: function (ajaxrequest, ajaxOptions, thrownError) {
$("#openmodal").html('Failed to load more content');
}
});
});
Additionally, this is the Action Method I have for the Modal Popup, in HomeController:
public ActionResult NewsModal(NewsModel tempData)
{
NewsModel currentItem = new NewsModel();
currentItem = tempData;
return PartialView("NewsModal", currentItem);
}
You can do by make a click event by using Anchor tag instead ActionLink,
and in that you can do like this.
Open a Modal by jQuery
function openModal()
{
$('#newsModal').modal('show');
}
// $('#newsModal').modal('toggle');
// $('#newsModal').modal('show');
// $('#newsModal').modal('hide');
OR can do directly with data-target,
<button type="button" data-toggle="modal" data-target="#newsModal">Launch modal</button>

Resources