In C# I do this from a controller:
public ActionResult GetCompanies()
{
var vm = new CompanyViewModel { jsonData = JsonConvert.Serialize(_repository.All<Company>()) };
return View(vm);
}
ViewModel looks like this:
public CompanyViewModel
{
public string jsonData {get;set}
}
On the client side:
#model MyWebApp.ViewModels.CompanyViewModel
#Scripts.Render("~/bundles/knockout")
<script type="text/javascript">
var serverData = <!-- Many Things To Do Here -->
</script>
In the part <!-- Many Things To Do Here --> there a few things you can do to put the server data into a JavaScript Object.
What is the best way to do this, because I have had problems with JSON.parse to do with some characters JSON.NET serializes.
Is just putting the plain data in there okay (it works): var serverData = #Html.Raw(#Model.jsonData)
What other things should/can be done here?
Rather than creating a model just to hold a JSON string, just pass the plain .NET object to your view, and serialize it to JSON there:
In your controller:
public ActionResult GetCompanies()
{
return View(_repository.All<Comapny>());
}
Then in your view:
<script>
var companies = #Html.Raw(JsonConvert.SerializeObject(Model));
</script>
If you want/need a strongly typed model in your view, you should change your CompanyViewModel to this:
public class CompanyViewModel
{
public IList<Company> Companies {get; set;}
//Or whatever sort of collection your repository returns
}
And in your controller
public ActionResult GetCompanies()
{
var vm = new CompanyViewModel { Companies = _repository.All<Company>() };
return View(vm);
}
Then in your view:
#model MyWebApp.ViewModels.CompanyViewModel
<script>
var companies = #Html.Raw(JsonConvert.SerializeObject(Model.Companies));
</script>
Related
I was wondering what's the best approaching to read data in ASP.NET.
Method 1:
In the controller:
public ActionResult CatPerfomanceReportCreate(string dateStart, string dateEnd)
{
ViewBag.DateStart = dateStart;
ViewBag.DateEnd = dateEnd;
return View();
}
and the View:
#{
var readData = MyDataClass.GetData(ViewBag.DateStart, ViewBag.DateEnd)
}
..
..
..
<table>,,,,,<table>
Method 2:
In the controller:
public ActionResult CatPerfomanceReportCreate(string dateStart, string dateEnd)
{
ViewBag.Data = MyDataClass.GetData(dateStart, dateEnd);
return View();
}
and the View:
#{
List<MyDataClass> data = ViewBag.Data;
}
..
..
..
<table>,,,,,<table>
Method 1 read the heavy data in the View and Method 2 in the controller.
Thanks
Neither.
Method2 is slightly better than Method1 because it comply with the Dumb View method. Both of those method make use of the ViewBag dynamic which can but not intended to save information about your information you want to present to the user. Strongly Type elements in most cases are much preferred than dynamics and giving you the full force of the compiler behind it.
Let me suggest Method3 that is much better suited method for MVC. It is creating a Model of the data you want to use in your View and use it.
Model:
public class CatPerfomanceReport
{
public string DateStart { get; set; }
public string DateEnd { get; set; }
}
Controller:
public ActionResult CatPerfomanceReportCreate(string dateStart, string dateEnd)
{
var model = new CatPerfomanceReport
{
DateStart = dateStart,
DateEnd = dateEnd
};
return View(model);
}
Partial of View:
#model CatPerfomanceReport
<h1>Start: #Model.DateStart</h1>
<h1>End: #Model.DateEnd</h1>
I am using Html.RenderAction in my View to call a method that is in my controller. The controller method returns a custom object, I want to know how would I be able to use this returned object in the view.
View
//at the top
#model ServiceCheckerUI.Models.DeleteDeliverableModel
#{ Html.RenderAction("retrieveDeliverableInfo","DeliverableManagement", new {uniqueId = element});}
//Trying to use the model property
Model.deliverableResponse.{properties}
Controller
public ActionResult retrieveDeliverableInfo(string uniqueId){
var response = _target.DoSomething();
return PartialView("DeleteDeliverable", new DeleteDeliverableModel {deliverableResponse = response});
}
Model
namespace ServiceCheckerUI.Models
{
public DeleteDeliverableModel
{
//omit
public GetDeliverableResponse deliverableResponse {get;set}
}
}
The GetDeliverableResponse object has fields like id, name etc which are strings and ints.
RenderAction is used to directly write response to the page and helps in caching the partial view. Your method should return partial view instead of GetDeliverableResponse. You can define the partial view and use GetDeliverableResponse as it's model.
public ActionResult RetrieveDeliverableInfo(string uniqueId)
{
var response = _target.DoSomething();
return PartialView("_Deliverable", response );
}
Here _Derliverable would be your partial view which will have GetDeliverableResponse as model.
To keep it more neat you can also Wrap the response object in a dedicated model class of _Derliverable like this:
class DerliverableModel
{
public GetDeliverableResponse Derliverables { get; set; }
}
now in your action method you need to pass the object of this model:
return PartialView("_Deliverable", new DerliverableModel { Derliveries = response });
I have a server-generated object that I need to convert to a JSON object for JavaScript to consume. I prefer to render this JSON object directly into a JS variable when the view renders to prevent an additional HTTP request.
This is in my controller:
public virtual JsonResult GetTheThings()
{
return Json(new
{
foo = "hello world",
bar = 3,
}, JsonRequestBehavior.AllowGet);
}
I can access this directly at http://localhost:32243/MyController/GetTheThings and I get the following rendered in my browser.
{"foo":"hello world", "bar":3}. Perfect!
So, now I basically just want to render the result of this view into a string. How do I do this? What I have below does not work, but hopefully it give you the idea.
This is my attempt
<script>
var myObj = #Html.RenderPartial(MVC.MyController.GetTheThings());
</script>
Note that I am also using T4 Templates.
In the end, this is what I want to be rendered in the view.
<script>
var myObj = {"foo":"hello world", "bar":3};
</script>
Since you only want the object to be rendered when the view is rendered (and not from an AJAX call), your best bet is probably to make it part of your model. Create a string property and save the JSON as a string, then use JSON.parse in your View to convert it to an object.
Example:
<script>
var myObj = JSON.parse("#Html.Raw(Model.JsonString)");
</script>
Much cleaner that way, and there really isn't any good reason to have your controller doing this since you aren't requesting the object via AJAX.
You could create an HtmlHelper extension like so and instead of using a JsonResult, use a strongly-typed view (assuming using JSON.Net):
public static class HtmlHelperEx
{
public static string ToJson(this HtmlHelper html, object obj)
{
return JsonConvert.SerializeObject(obj);
}
}
Controller Action:
public ActionResult Index()
{
return View(new ModelToSerialize());
}
Then use it in your view like:
#model ModelToSerialize
<script type="text/javascript">
var myObj = #Html.ToJson(Model)
</script>
You would theoritically be able to do it like this:
<script>
var myObj = json.parse('#Html.RenderPartial(MVC.MyController.GetTheThings());');
</script>
Although, GetTheThings() will not actually fire here, it's just a T4MVC placeholder. You should probably store your value into a view model, and get it into javascript like below. If you want to make a separate call to a controller to get this value, it will need to be an ajax call.
public class MyController
{
public ActionResult MyView(){
var vm = new MyViewModel();
vm.MyObjectAsJsonString = GetMyJsonString();
return View(vm);
}
public string GetMyJsonString(){
return ""; //get your json
}
}
public class MyViewModel
{
public string MyObjectAsJsonString{ get; set; }
}
#model MyViewModel
<script>
var myObj = json.parse('#Model.MyObjectAsJsonString');
</script>
To do it via ajax:
<script>
$.ajax({
url: '#Url.Action(MVC.MyController.GetTheThings())',
type: 'get',
}).done(function (result){
var myObj = result;
});
</script>
<script>
var myObj = '#Html.RenderPartial("Getthethings","controller name");'
</script>
Use the #Html.Raw(...) wrapper.
In my own project, I do refer to the existing model coming down in from the controller itself, but there's no reason you can't get the same effect as a partial...it's just not really the core purpose of using async calls...which you should be using instead of relying on the html rendering engine to do your 'dirty' work.
I am new to mvc and cannot figure out how to pass a single column of data to the view.
I have connected my db with ado.net entity model to models.
Then in my controller I have :
public class HomeController : Controller
{
shdesignEntities2 _db;
public ActionResult Index()
{
_db = new shdesignEntities2();
ViewData.Model = _db.tblKategoris.ToList();
return View();
}
}
In the view :
#foreach(var m in ViewData.Model)
{
<p>Kategori Ad :</p><p> #m.kategori_ad </p>
}
When I do like this , I pass the whole table data to the view where I only need a single column of information.
How can I only pass data from the column kategori_ad ?
Use Select:
ViewData.Model = _db.tblKategoris.Select(x => x.kategori_ad).ToList();
You can use LINQ to find the object that you want and then pass it to the view, do something like this:
public ActionResult Index()
{
_db = new shdesignEntities2();
ViewData.Model = _db.tblKategoris.Select(x => x.kategori_ad).ToList();
return View();
}
That way ViewData.Model only has the object that matches the linq query.
Here you can find more about Linq to retrieve data from a collection in C#: http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b
In Controller
ViewData["Rows"] = (from c in _db.tblKategoris
select c.kategori_ad).ToList();
View
#foreach(var m in (List<string>)ViewData["Rows"])
{
<p>Kategori Ad :</p><p> #m </p>
}
You may look at ViewModels. Also by this way you can use smaller part of data exposed.
For example
public class KategoriViewModel
{
public IEnumerable<Kategori> Kategoriler { get; set; }
}
Then you should add a controller action like
public ActionResult Something()
{
var model = new KategoriViewModel;
model.Kategoriler = your query..;
return View(model);
}
In view
#model KategoriViewModel
#foreach(var m in ViewData.Model)
{
<p>Kategori Ad :</p><p> #m.kategori_ad </p>
}
I have a strongly typed view of type ProductListingViewModel which in turn contains a ProductViewModel. (both custom view models).
I have some form elements on my page and these are created like so:
<%: Html.DropDownListFor(m => m.ProductViewModel.CategoryId, Model.Categories)%>
which generates the HTML:
<select name="ProductViewModel.CategoryId" id="CategoryId">
With the default model binding I expected that when I post to my controller action which accepts a parameter of type ProductListingViewModel, that it'd know to populate the ProductViewModel.CategoryId with the relevant data.
The name of the select list seems to indicate that it knows there's a ProductViewModel with a CategoryId property however when I post to my controller method, the ProductViewModel is null. If I create this during construction of the ProductListingViewModel then it's no longer null but the default binder doesn't seem to be populating the properties as I expected.
Is this a case for a custom model binder or am I just missing something fundamental?
Cheers.
Let me try to summarize (correct me if I am wrong).
Model:
public class ProductListingViewModel
{
public ProductViewModel ProductViewModel { get; set; }
public IEnumerable<SelectListItem> Categories { get; set; }
}
public class ProductViewModel
{
public string CategoryId { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
var model = new ProductListingViewModel
{
Categories = new SelectList(new[]
{
new { Value = "1", Text = "category 1" },
new { Value = "2", Text = "category 2" }
}, "Value", "Text")
};
return View(model);
}
[HttpPost]
public ActionResult Index(ProductListingViewModel model)
{
return View(model);
}
}
View:
<% using (Html.BeginForm()) { %>
<%: Html.DropDownListFor(m => m.ProductViewModel.CategoryId, Model.Categories)%>
<input type="submit" value="OK" />
<% } %>
Now when you submit the form you will get:
model.ProductViewModel.CategoryId = the id that was selected in the drop down list
Isn't what you are after?
It seems to me that the default binder should work in this case.
Did you try using Fiddler for checking the data sent from the client?
What exactly is the signature of the controller action?