Async loading inside cshtml page - c#

It it possible to use Task (System.Threading) inside Razor??
What i'm trying to do is this: I have a table that I want to async fill.
Look at the code:
#{
Func<dynamic, object> preenche =
#<text>
<tr><td>oi1</td><td>oi2</td></tr>
</text>;
}
...
<tbody>
#Task.Factory.StartNew(() =>
{
foreach(Apontamento ap in Model.apontamentos)
{
preenche(ap);
}
})
</tbody>
The output is just this: System.Threading.Tasks.Task
Is it possible? Or I can just have what i'm trying to do using Ajax?

If you want the page to render and appear instantly and then have something happen later on (say an operation takes 5 seconds to complete) then you can get the page to update when the data is available by doing something like this (More information about .getJSON).
On your Razor view you can add some JavaScript:
<script type="text/javascript">
$.getJSON('LongRunningAsyncTask', function (result)
{
// Populate table or other actions with: result.Data
// ...
});
</script>
Then in your Controller you would have the tasks like this:
public JsonResult LongRunningAsyncTask()
{
// Show this is async and won't render straight away...
System.Threading.Thread.Sleep(5000);
// Build up our view model
var viewModel = new TestViewModel();
// Send back as a Json result
var result = new JsonResult();
result.Data = viewModel;
return Json(result, JsonRequestBehavior.AllowGet);
}

You should NOT do this in the View. Make asynchronous action but when you start rendering the view all the data should be ready.

Related

Call function from cshtml to cshtml.cs using Models

I am new to asp.net core and Razor, i am trying to call a function from cshtml page to his inner cs page:
<button onclick="#{Model.GetUserInfo(1);};" type="submit">Search</button>
cshtsml.cs
public UserInfo GetUserInfo(int userId)
{
using (var client = new HttpClient())
{
var response = client.GetAsync($"localhost:44322/api/User/user/{userId}{userId}");
var body = response.Result.Content.ReadAsAsync<UserInfo>().Result;
return body;
}
}
I would like to get the information back from the api and display the information that i received.
With this code if i put { } around the Model.GetUserInfo(1); it doesn't display the button, without the { } it just doesn't compile.
Any of you can help me with it? thanks.
Step 1 - You can write a javascript function which will send an ajax request to your controller method
Step 2 - Return the data you want from this method
Assuming your controller name is Home, you can do something like this-
<button onclick="GetData()" type="submit">Search</button>
function GetData() {
$.get("/Home/GetUserInfo", function (data) {
// Here put what do you want from received data
});
}

How to display an alert message from .cshtml view - asp.net mvc

I have two action result one sending a string and another loading the view
public ActionResult getTheString()
{
string message = //doing some thing ;
myModel myModel = new myModel();
myModel.property1 = message ;
return loadView(myModel);
}
public ActionResult loadView(myModel model)
{
return view (model);
}
loadView.cshtml
#model project.Models.myModel
#{
if(Model.property1 !=" ")
{what to do to show it as alert }
}
Here I am getting the prperty like model.property1 if it has some thing show the alert with that string and then load, if message does not contain anything then simply load.
Not permitted to use TempData , ViewBag , ViewData.
Not permitted to use Script tag in view . it has to be in a seperate js file
You could check with some simple Razor syntax
#if(!string.IsNullOrEmpty(Model.Property1)) {
<script>alert("#Model.Property1");</script>
}
you can use javascript and give alert once page is loaded.
<script type="text/javascript">
window.load = function() {
#if(!string.IsNullOrEmpty(Model.Property1)) {
alert("blah blah");
}
}
</script>

How to get value from Javascript popup call in MVC ActionResult ?

I have a javascript function that calls a MVC action result which in turn will populate the correct View. I need to pass .Net code with that pop up call, is it possible?
So for example I need to pass a integer from the model over so I can use it in my action result.
a button click calls this function
ShowPopUp = function () {
window.showModalDialog("/FileUpload/GetPopupData", "wndPopUp", "width=300,height=500");
}
and here is the action result
public ActionResult GetPopupData()
{
//Call the pop up view and populate it accordingly
return new GetDocumentTypeAction<ActionResult>
{
OnLoaded = m => View("../../Areas/Exports/Views/FileUpload/FileUpload", m),
OnErrorOccured = (m) => Redirects.ToErrorPage()
}.Execute(GtsClient);
}
How will I send the int over and how will I read it in the action result?
In your view, render out the integer you want from the model as a JavaScript variable that you can reference in your ShowPopUp() function.
<script>
var viewId = <%=Model.ViewId%>;
ShowPopUp = function () {
window.showModalDialog("/FileUpload/GetPopupData/" + viewId,
"wndPopUp", "width=300,height=500");
}
</script>

How to update a View without Postback in MVC3

How can I update a dropdownlist in MVC3. I want to refill it with latest data filled by some other view, but I do not want to postback the view and want to achieve it with jquery.
I have a dropdownlist like:
#Html.DropDownListFor(m => m.Department, Model.Departments)
#Html.ValidationMessageFor(m => m.Departments)
<input type="button" value="Refresh" id="btnrefresh" />
I have written jquery code to call controller's method:
$("#btnrefresh").click(function () {
var ref = '#Url.Action("RefreshDepartments")';
var model = '#Model.ToJson()';
var data = { empModel: model };
$.getJSON(ref, data, function (result) { alert(result.message); });
return false;
});
And Here is the controller method:
public ActionResult RefreshDepartments(EmployeeModel empModel)
{
empModel.Departments = GetDepartments();
empModel.Roles = GetRoles();
return Json(new { message = "Updated successfully"}, JsonRequestBehavior.AllowGet);
}
How can I update the dropdownlist with latest values on clicking "Refresh" button without any postback?
Is it a good idea to pass the model to the controller and update the model properties? What other ways are possible ?
It doesn't look to me like you need the model to be posted to your controller for what you're doing. In addition, yes, you absolutely can do this with jquery! On a side note, you could also do it with an Ajax.BeginForm() helper method, but lets deal with your jquery example.
Rather than complexify your jquery with your #Url.Action, you can simply call the path itself.
$("#btnrefresh").click(function () {
var ref = 'ControllerName/RefreshDepartments';
$.each(result, function (index, val) {
$('#whateverYourRenderedDropdownListHtmlObjectis')
.append($("<option></option>")
.attr("value", val.Text)
.text(val.Text));
});
});
Now, for your controller...
public JsonResult RefreshDepartments()
{
return Json(GetDepartments, JsonRequestBehavior.AllowGet);
}
private SelectList GetDepartments
{
var deparments = GetDepartments;
SelectList list = new SelectList(departments);
return list;
}
This is an alternative to returning the model. It allows you to manipulate the raw JSON instead. Hope it helps!
You almost did it all! Why don't you send the data, I mean list, by RefreshDepartments action? You sent a message to view, so you can send the list similarly and instead of alerting the result you can fill the dropdownlist. something like this:
public ActionResult RefreshDepartments(EmployeeModel empModel)
{
return Json(new { departments = GetDepartments()}, JsonRequestBehavior.AllowGet);
}
$.getJSON(ref, data, function (result) {
$("#Department").html("");
for (var i = 0; i < result.departments.length; i++) {
var item = result.departments[i];
$("#Department").append(
$("<option></option>").val(item.Id).html(item.Name);
);
});
});

MVC 3 - How do you return a Display Template from an action method?

I have a view that displays a list of comments. It does this via the DisplayTemplate. All I have to do is something like #Html.DisplayFor(x => x.BlogPost.PostComments) and all the comments render appropriately.
There is a form at the bottom of the page to add a new comment. This page utilizes progressive enhancement. So if javascript is disabled then the form submits like normal, adds the comment to the database, then redirects to the action that renders the blog post. However, if javascript is available then jQuery hijacks the form's submit and makes the post via ajax. Well because the comment markup is in a display template, I don't know how to return it from the action method so that jQuery can drop it on the page.
I know how to do this with partial views. I would just have the action method return the right partial view and jquery would append the response to the comment container on the page.
Before I go chopping out my display template in favor of a partial view, is there a straight forward way that I'm missing to send back a display template from the controller?
Here is my action method:
public ActionResult AddComment(PostComment postComment)
{
postComment.PostedDate = DateTime.Now;
postCommentRepo.AddPostComment(postComment);
postCommentRepo.SaveChanges();
if (Request.IsAjaxRequest())
return ???????
else
return RedirectToAction("BlogPost", new { Id = postComment.BlogPostID });
}
When the page loads it doesn't need to worry about it because it uses the templates in the standard way:
<div class="comments">
#Html.DisplayFor(x => x.BlogPost.BlogPostComments)
</div>
I just want to know how I might send a single comment that utilizes the display template back to jQuery.
You may try returning the partial HTML representing the newly posted comment:
if (Request.IsAjaxRequest())
{
return PartialView(
"~/Views/Shared/DisplayTemplates/Comment.cshtml",
postComment
);
}
and on the client side append this comment to the comments container:
$.post('#Url.Action("AddComment")', { ... }, function (result) {
$('#comments').append(result);
// or $('#comments').prepend(result); if you want it to appear on top
});
Does this question give you what you are looking for? Seems to indicate that you can call a HTML helper from an action.
Create a partial view /Shared/DisplayTemplate.cshtml with the following razor code:
#Html.DisplayFor(m => Model)
Then in your controller (or preferably in a base controller class) add a method along these lines:
protected PartialViewResult PartialViewFor(object model)
{
return PartialView("DisplayTemplate",model);
}
In the OP's case then:
public ActionResult AddComment(PostComment postComment)
{
postComment.PostedDate = DateTime.Now;
postCommentRepo.AddPostComment(postComment);
postCommentRepo.SaveChanges();
if (Request.IsAjaxRequest())
return PartialViewFor(postComment);
else
return RedirectToAction("BlogPost", new { Id = postComment.BlogPostID });
}

Categories