Is there a way to return HtmlHelper object from controller to view?
In code:
Controller:
public ActionResult SomeFunc(int id)
{
if (condition)
return Content();//here i would like to send Html.ActionLink("Text", "Action")
else
return Content();
}
The link will get handle in javascript:
$.get("", { id: $("#id").val() }).
done(function (data) {
if (data != 0) {
$("#someDOMID").val(data);
}
});
If you want the content to contain a raw html string then you can create a function to render a partial to a string serverside and return that.
You could then take it another step and create a generic ActionLinkPartial that contained one embedded #Html.ActionLink and accepted a model that had your action link configuration settings.
Something like...
protected string RenderPartialViewToString(string viewName, object model)
{
if (string.IsNullOrEmpty(viewName))
viewName = ControllerContext.RouteData.GetRequiredString("action");
ViewData.Model = model;
using (StringWriter sw = new StringWriter())
{
ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
viewResult.View.Render(viewContext, sw);
return sw.GetStringBuilder().ToString();
}
}
And use a model like...
public class ActionLinkModel
{
public string Text{get;set}
public string Action{get;set;}
}
Invoke it like...
var html = this.RenderPartialViewToString("Partials/Html/ActionLinkPartial", model);
If you only need to send a link as mentioned in your question then try this:
public ActionResult GetLink()
{
string url = Url.Action("Index", "Home", new { id = 1 });
return Content(url);
}
Otherwise, it's better to use the Partial View approach.
Related
How I can get access to variable (which was added as attribute to Model in my controller) in JavaScript and how I can work with properties of it?
My model:
public class Category {
private Long id;
private String name;
private List<Recipe> recipes = new ArrayList<>();
}
My controller:
#RequestMapping(path = "/", method = RequestMethod.GET)
public String showAllCategories(Model model) {
List <Category> categories = categoryService.findAll();
model.addAttribute("categories", categories);
return "index";
}
On my web page I need to show all categories (no problem, using Thymeleaf th:each="category : ${categories}") and have ability add new category to categories variable and set its properties (id, name, recipes for example).
So, how I can get access to variable 'categories' in JavaScript, and how I can add new element and set properties in JavaScript?
You can make an ajax call to this method
// using jquery
$.ajax({
url:'/',
success:function(response){
// get the return pf the method here
// can be assigned to any variable
}
java method change
#RequestMapping(path = "/", method = RequestMethod.GET)
public String showAllCategories(Model model) {
//rest of code
return (the value which which you want to assign to model property);
}
Explore more about ajax
You have to create an API. Rest for example.
The idea is to create methods callable by javascript(via AJAX for example), and do the operations you need to do in java.
Here you have some pseudocode:
#RequestMapping(path = "/addCategory", method = RequestMethod.GET)
public boolean AddCategory(Model model) {
//Do your logic to add category
if (/*everything went good*/) return true;
else return fale;
}
Why you want to use Model?, when you can directly access the object as JSON:
JS Snippet using Angular:
$http.get('/app/get').then(function(response) {
$scope.categoryList = response.data;
}, function(response) {
});
JS Snippet using Jquery:
$.ajax({
url: "/app/get",
type: 'GET',
success: function(response) {
var categoryList = response.data;
console.log(categoryList);
}
});
Java Snippet:
#RestController
#RequestMapping
public class Controller {
#RequestMapping(path = "/get", method = RequestMethod.GET)
public List <Category> showAllCategories() {
return categoryService.findAll();
}
}
I am using angularjs in asp.net
I made a controller with CRUD and am trying to get data from angularjs controller using $http service
Route params is getting correct querys from url, i tested that, but i get undefined error when requesting data
What am i doing wrong? :(
SongsController.cs method:
public ActionResult Index(string id)
{
/*var result = db.Songs.ToList();
return Json(result, JsonRequestBehavior.AllowGet);*/
string searchString = id;
var songs = from m in db.Songs
select m;
if (!String.IsNullOrEmpty(searchString))
{
songs = songs.Where(s => s.Title.Contains(searchString));
}
return Json(songs, JsonRequestBehavior.AllowGet);
}
songsService.js:
myApp.factory('songsService', ['$http', function ($http) {
var songsService = {};
songsService.getSongs = function (param) {
return $http.get('/Songs/Index/' + param);
}
return songsService;}])
songsController.js:
myApp.controller('songsController', ['$scope', '$routeParams', 'songsService', function ($scope, $routeParams, songsService) {
var search = $routeParams.query;
if (search == 'undefined' || search == null)
search = '';
getSongs(search);
function getSongs(searchText) {
songsService.getSongs(searchText)
.success(function (data) {
$scope.songs = data;
})
.error(function (error) {
$scope.status = 'Unable to load data: ' + error.message;
console.log($scope.status);
});
}}]);
EDIT:
Song class:
using System;
using System.Collections.Generic;
public class Song
{
public int ID { get; set; }
public string Title { get; set; }
public string Artist { get; set; }
public virtual ICollection<Navigation> Navigations { get; set; }
}
EDIT2: Navigation class:
using System;
public class Navigation
{
public int ID { get; set; }
public int SongID { get; set; }
public int PlaylistID { get; set; }
public virtual Song Song { get; set; }
public virtual Playlist Playlist { get; set; }
}
EDIT3:
If I name my .cs controller SongsController and navigate to url songs/index/something i get popup if i want to open or save something.json and just get redirected back to my default url defined by ngroute (#/songs/)
But, if i name .cs controller something else, like RandomController, if i navigate to same url i get this error:
A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.Navigation_7A1A3B789B740F23BAB0A6DAABE519BE3AF91C300893047C23FF2FD8C44E6705'.
EDIT4: I've come to point at which everything if my SongsController.cs looks like this:
public ActionResult Index(string id)
{
var song = new List<Song>
{
new Song{Title="Paint It Black",Artist="Rolling Stones"},
new Song{Title="People Are Strange",Artist="The Doors"},
new Song{Title="With Or Without You",Artist="U2"},
new Song{Title="Wish You Were Here",Artist="Pink Floyd"},
new Song{Title="Fluorescent Adolescent",Artist="Arctic Monkeys"},
new Song{Title="La Guitarra",Artist="Orjan Nilsen"},
new Song{Title="Ping Pong",Artist="Armin Van Buuren"},
new Song{Title="Fade Out Lines",Artist="The Avenger"},
new Song{Title="Redemption Song",Artist="Bob Marley"},
new Song{Title="Wherever I May Roam",Artist="Metallica"},
};
return Json(songs, JsonRequestBehavior.AllowGet);*/
}
If it' like that everything works, but if it looks like i've wrote in original post i get undefined error when i run $http.get :/
EDIT5: Okay, I believe the problem is i'm trying to send objects containing array of Navigation class objects, how can i solve this? :(
You have a circular reference on your Song class.
When the Json serializer tries to process it, it finds the Navigations property and tries to serialize that as well, the problem is that each Navigation object on that collection have a instance of the same Song, so it enters a infinite loop trying to serialize all of it over and over again.
That happens because EntityFramework has its lazyloading and automatically populate the classes as the serializer tries to access them.
To fix it, you can do two things, simply disable the lazyloading for that call in particular:
public ActionResult Index(string id)
{
db.Configuration.LazyLoadingEnabled = false;
string searchString = id;
var songs = from m in db.Songs
select m;
if (!String.IsNullOrEmpty(searchString))
{
songs = songs.Where(s => s.Title.Contains(searchString));
}
return Json(songs, JsonRequestBehavior.AllowGet);
}
The other option is to create a model with only the data you need to return and populate it manually (or using a mapper tool).
public ActionResult Index(string id)
{
db.Configuration.LazyLoadingEnabled = false;
string searchString = id;
var songs = from m in db.Songs
select m;
if (!String.IsNullOrEmpty(searchString))
{
songs = songs.Where(s => s.Title.Contains(searchString));
}
var mappedSongs = songs.Select(it => new { Title = it.Title, Artist = it.Artist }).ToList();
return Json(mappedSongs , JsonRequestBehavior.AllowGet);
}
Is it possible to return 2 separate views to an ajax call in Asp.net?
for example, if foo1 and foo2 are 2 ActionResult methods each returning a view?
return Json(new { a = foo1(), b = foo2() });
currently attempting this, the end result is that javascript gets it back as a class object rather then the actual view, anybody know how to get the resulting rendered html instead?
EDIT: I guess what I'm actually going for, is there a way for me to return the rendered view in string format?
Yes their is a way of returning view in string format.
For this you need to do following things:
1.You need some method in which you can pass your viewname along with object model. For this please refer below code and add to your helper class.
public static class RenderViewLib
{
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();
}
}
}
The above code will return your view in string format.
2.Now call above method from your json call like this:
[HttpPost]
public JsonResult GetData()
{
Mymodel model = new Mymodel();
JsonResult jr = null;
jr = Json(new
{
ViewHtml = this.RenderPartialView("_ViewName", model),
ViewHtml2 = this.RenderPartialView("_ViewName2", model),
IsSuccess = true
}, JsonRequestBehavior.AllowGet);
return jr;
}
and you will get your view as string format from your json call.
Hope this is what you are looking for.
I have this modelView
public class Ue
{ public class uEkranModel
{
public List<Grup> Grup = new List<Grup>();
private List<Secim> _secim;
public List<Secim> secim
{
get
{
if (_secim == null)
_secim = new List<Secim>();
return _secim;
}
set { _secim = value; }
}
}
public class Secim
{
public Guid uGuid { get; set; }
public Guid fGuid { get; set; }
}
}
I need to fell the List secims items with JS and post it back to controller.
I have tried to :
1)initialize the list in the controller :
Controller :
gidecek.Data = new Models.Ucak.UcakDeneme.uEkranModel();
gidecek.Data.secim.Add(new Models.Ue.Secim { uGuid = new Guid() });
gidecek.Data.secim.Add(new Models.Ue.Secim { uGuid = new Guid() });
View :
#using (Html.BeginForm("deneme", "U", FormMethod.Post, new { id = "secimTamam", style = "display:none" }))
{
#Html.EditorFor(m => m.Data.secim[0])
#Html.TextBoxFor(m => m.Data.secim[0].uGuid, new {id="gidis" })
}
JS :
$("#Data_secim_0__ucusGuid").attr("value", index);
This way , when the code is executed the value field of the textboxfor is changed(when the JS fired) but when I check the post data in controller , it is NULL.
also tried :
$("#Data_secim_0__ucusGuid").val(index);
which doesnt cahnge the value of teh textbox.
What I need is to fill the model values with js and post the form with js as well.(The data user is selecting is different, I am just posting back the GUID of the items within a form.)
2 possible issues. Your getter is initializing a new List<Secim>. Try initializing it in the constructor
public class uEkranModel
{
public uEkranModel()
{
secim = new List<Secim>();
}
public List<Secim> secim { get; set;}
....
}
Also I have seen other posts on SO indicating problems posting back GUID's (and one solution that was accepted was to use a view model with the GUID's converted to strings)
I have a method which registers a vote for a comment. If there are no errors while casting the vote, I return a small snippet of html via a PartialViewResult to update the page.
If it does not succeed, nothing should happen. I need to test for this condition on the client side.
The server-side method:
[HttpPost]
public PartialViewResult RegisterVote(int commentID, VoteType voteType) {
if (User.Identity.IsAuthenticated) {
var userVote = repository.RegisterVote((Guid)Membership.GetUser().ProviderUserKey, commentID, voteType);
if (userVote != null) {
return PartialView("VoteButtons", userCommentVote.Comment);
}
}
return null;
}
The client side script:
$(document).on("click", ".vote img", function () {
var image = $(this);
var commentID = GetCommentID(image);
var voteType = image.data("type");
$.post("/TheSite/RegisterVote", { commentID: commentID, voteType: voteType }, function (html) {
image.parent().replaceWith(html);
});
});
If the vote was recorded, the "html" variable containes markup as expected. If it does not succeed (i.e. null was returned) then the "html" variable is instead a "Document" object with a parse error.
Is there a way to return an empty string from the PartialViewResult and then just test for length? Is there a different/better way to do this?
Change your method signature from: public PartialViewResult
To: public ActionResult
Then instead of returning null, return this:
return Json("");
This will allow you to return a partial view if successful, if not, it will just return JSON with an empty string as the value. Your current JS will work as is. From MSDN:
The ActionResult class is the base class for action results.
The following types derive from ActionResult:
ContentResult
EmptyResult
FileResult
HttpUnauthorizedResult
JavaScriptResult
JsonResult
RedirectResult
RedirectToRouteResult
ViewResultBase
This is what allows you to return different derived types in your method.
It would be better to return a JsonResult as,
[HttpPost]
public JsonResult RegisterVote(int commentID, VoteType voteType)
{
JsonResult result = new JsonResult();
object content;
if (User.Identity.IsAuthenticated)
{
var userVote = repository.RegisterVote((Guid)Membership.GetUser().ProviderUserKey, commentID, voteType);
if (userVote != null)
{
content = new
{
IsSuccess = true,
VoteButtons = userCommentVote.Comment
};
}
else
{
content = new { IsSuccess = false };
}
}
result.Data = content;
return result;
}
In Ajax call, you can validate if IsSuccess is true or false.