I have a view named Index.cshtml with a table of users (create/edit/update functionalities).
When buttons (create/edit/update) are clicked I have a jQuery dialog for it. Next I use an ajax post like this:
Edit >> call an action controller for editing and return a json >> update row table with javascript
Delete >> call an action controller for deleting and return a json >> delete row table with javascript
Create >> call an action controller for creating and redirect to Index.cshtml >> ???
For the create part, I have a problem: I would like "simply" to display my view but I am in an ajax post. I don't know how to proceed.
Here is my code (submitting data and then refreshing the view):
$.post($(this).attr('action'), $(this).serialize(), function (data, status) {
$('#my-modal').modal('hide');
if (data.operation == 'edit') {
// Edit
var row = $('#' + data.userid);
row.children(':eq(0)').text(data.company);
row.children(':eq(1)').text(data.username);
row.children(':eq(2)').text(data.email);
row.children(':eq(3)').text(data.firstname);
row.children(':eq(4)').text(data.lastname);
} else if (data.operation == 'delete') {
// Delete
var row = $('#' + data.userid);
row.remove();
} else {
// Create
alert(data);
$("#userList").html(data);
}
})
As you can see, I check the data.operation which tells me if I do an 'edit' or 'delete' of (last possibility) a 'create'. For the create the problem is that my entire view (< html> < body>...) is generated and added in my #userList div. That's duplicate things.
Maybe that's not the right thing to do?
Thanks.
UPDATED
Here is my Create action:
[HttpPost]
public ActionResult Create(UserCreateViewModel viewModel)
{
if (!ModelState.IsValid)
{
this.Response.StatusCode = 400;
return PartialView("Create", viewModel);
}
var userDTO = new UserDTO();
Mapper.Map(viewModel, userDTO);
_requestServiceClient.CreateNewUser(userDTO);
return RedirectToAction("Index");
}
Here is my Index action:
[Authorize]
public ActionResult Index(string q, int? page)
{
var users = _requestServiceClient.GetUsers();
...
...
if (Request.IsAjaxRequest())
return PartialView(userListPaged);
else
return View(usersListPaged);
}
After relexion, in case of 'create' maybe it is better in my view to simply reload the page like this:
...
} else if (data.operation == 'create') {
// Create >> refresh the page
location.reload();
}
Thanks anyway.
If your list is not too long I would suggest to send back the complete list in every ajax request, doesn't matter if update, create or delete.
So you can remove your data operation check (your :eq(0) stuff will fail if you change the order of the columns some day) and simply put the result from the ajax request in your #userlist div.
EDIT
But to solve your create problem:
Just replace in the Create action this line:
return RedirectToAction("Index");
with this line:
return PartialView("Index", _requestServiceClient.GetUsers());
and it should return only the new list.
EDIT2
Ok, your Index.cshtml seems to have the complete layout, not just the list as I thought. So you have to do this first:
Move just the HTML code required to build the list in a seperate View, name it _List.cshtml for example
At the place where the HTML code was in your Index.cshtml put #Html.Partial("_List") in there
At this point your index view should look the same as before but you have your list view seperatly
Change my example above to not return the Index but the _List partial:
return PartialView("_List", _requestServiceClient.GetUsers());
I hope that works for you.
Place this code into your partial view:
#{
Layout = null;
}
This code says that you don't need a master view for this page.
Related
I am trying to pass list of data through viewbag from controller to partial view but getting error
in login form after submitting data taking it from formcollection through HttPost and once action complete it return to home page from there i am calling method Page_Init inside that in 'loadmessage' method i am trying to return list to a partial view "Header" based on condition.but not able to perform getting error
Home controller
[HttpPost]
public ActionResult Login(FormCollection form)
{
return View("Home");
}
in Home.cshtml
calling method page_init in controller
$.get("/Home/Page_Init",null, function (data) {
alert(data);
});
Home controller
public ActionResult Page_Init()
{
loadMessages();
return view("Home");
}
public ActionResult loadMessages()
{
List<MessageModel> lstMessages = new List<MessageModel>();
List<MessageModel> lstInfoMessages = new List<MessageModel>();
lstInfoMessages = lstMessages.Where(msg => msg.MESSAGE_TYPE.Equals(CommonConstants.SAFETY_MESSAGE_INFO, StringComparison.InvariantCultureIgnoreCase)).ToList<MessageModel>();
if (lstInfoMessages.Count > 0)
{
ViewBag.lstInfoMessages = 1;
ViewBag.lstInfoMessages1 = lstInfoMessages;
return PartialView("Header", lstInfoMessages);
}
}
also trying to go to partial view from Home view
#ViewBag.lstInfoMessages1
#if (ViewBag.lstInfoMessages == 1)
{
#Html.Partial("Header",ViewBag.lstInfoMessages1)
}
Expected that list of information should go to partial view and bind
Error:Not getting Exact syntax what to do and how to proceed the steps tried above throw error
#Html.Partial method does not accept the dynamic value – so we need to cast it to the actual type.
#model MessageModel //you need to give correct path of MessageModel
#ViewBag.lstInfoMessages1
#if (ViewBag.lstInfoMessages == 1)
{
#Html.Partial("Header", (List<MessageModel>)ViewBag.lstInfoMessages1)
}
In Header Partial view, you can retrieve list using #Model
I am trying to execute an action on a controller without redirecting to the associated view for that action. For a good example of what I am trying to achieve take a look at the music.xbox.com website. When you add a song to a selected playlist from a popup menu - the page just shows a notification without any redirect or refresh. how is this possible?
What I have is the following:
I have a _playlistPopupMenu partial view that renders the list of playlists as follows:
_PlaylistPopupMenu
#model List<OneMusic.Models.GetPlaylists_Result>
#if (Model.Count > 0)
{
<li style="height:2px" class="divider"></li>
foreach (var item in Model)
{
<li style="height:30px">#Html.DisplayFor(p => item.Name)
#Html.ActionLink(item.Name, "AddSong", "Playlist", new { playlistId = #item.PlaylistId, songId = 1 }, "")
</li>
}
}
The PlaylistController AddSong action is as follows:
public PartialViewResult AddSong(int? playlistId, int? songId)
{
if (ModelState.IsValid)
{
db.AddSongToPlaylist(playlistId, songId);
db.SaveChanges();
return PartialView("_AddToPlaylist", "");
}
return PartialView("_AddToPlaylist", "");
}
I am struggling with what to put in the _AddToPlaylist partial view which I think I need to be able to display a notification of some kind (Possiblly using PNotify add in for Bootstrap). MVC wants to always redirect to ../Playlist/AddSong?playlistId=1&songId=1
Any ideas on how to complete this last part of the problem would be great.
If you don't want "full page reloads" then you need to approach the problem slightly differently, using javascript to alter the page dynamically. A library such as JQuery might make manipulating the DOM a little easier.
Display the popup dynamically using javascript.
When the user hits OK/Submit on the popup, post the data back to the server using javascript, and have the controller you are posting to return some HTML.
Append the returned HTML block (partial view) to an existing div containing playlist tracks.
The most difficult part of this is the asynchronous post. Help with updating a div without reloading the whole page can be found in this question.
EDIT - Example
If you have a controller action (accepting POSTs) with the URL myapp.com/PlayList/AddSong/, then you'd set up JQuery to post to this URL. You'd also set up the data property with any form data which you'd like to post, in your case you'd add playistId and songId to the data property.
You'd then use the result of the AJAX query (HTML) and append it to the existing playlist HTML on the page. So assuming that you want to append the partial view's HTML to a div with ID playlistDiv, and assuming that your partial view returns HTML which is valid when appended to the existing playlist, then your javascript will look something like this:
var data = { playlistId: 1, songId: 1 };
$.ajax({
type: "POST",
url: 'http://myapp.com/PlayList/AddSong/',
data: data,
success: function(resultData) {
// take the result data and update the div
$("#playlistDiv").append(resultData.html)
},
dataType: dataType
});
Disclaimer: I can't guarantee that this code will work 100% (unless I write the program myself). There may be differences in the version of JQuery that you use, etc, but with a little tweaking it should achieve the desired result.
using System.Web.Mvc;
using System.Web.Mvc.Html;
public ActionResult Index()
{
HtmlHelper helper = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView(ControllerContext, "Index"), new ViewDataDictionary(), new TempDataDictionary(), new System.IO.StringWriter()), new ViewPage());
helper.RenderAction("Index2");
return View();
}
public ActionResult Index2(/*your arg*/)
{
//your code
return new EmptyResult();
}
in your controller you must add bottom code:
public ActionResult Index(string msg)
{
if (Request.Url.ToString().Contains("yourNewExampleUrlWithOutRedirect.com"))
{
string html = "";
using (System.Net.WebClient client = new System.Net.WebClient())
{
client.Encoding = Encoding.UTF8;
html = client.DownloadString("https://NewExampleUrl.com/first/index?id=1");
}
Response.Write(html);
}
...
}
your view must be empty so you add bottom code
#{
ViewBag.Title = "sample title";
if (Request.Url.ToString().Contains("yourNewExampleUrlWithOutRedirect.com"))
{
Layout = null;
}else
{
Layout ="~/Views/Shared/_Layout.cshtml"
}
}
#if (Request.Url.ToString().Contains("yourNewExampleUrlWithOutRedirect.com")==false)
{
before view like :
<div>hello world</div>
}
I have the following scenario, where I have one model (named Model A) in a view (View1).
This view initially loads a partial view (Partial View 1)
On button click of partial view, I am trying to pass the id generated to another partial view (Partial View 2).
But I am getting an error saying View 1 cannot be found, which loaded without any issues on first run.
If I remove the else statement, the page successfully reloads after submission.
Any tips on passing this model object successfully to the other view please.
I put id=1 and tested it and the same error occured.
I tried RenderAction, RenderPartial and all these failed
Page
#model MyModel
#{
if (ViewBag.Created ==0) {
#Html.Partial("CreateView1",Model);
}
else
{
{ Html.Action("Action2", "Area/Controller2", new { id = Model.Id }); }
}
}
Controller methods:
Controller 1:Entry point of view
[Route("{CreateView1}")]
public ActionResult Create() {
ViewBag.Created = 0;
return View(new MyModel());
}
[Route("{CreateView1}")]
[HttpPost]
public ActionResult Create(MyModel model) {
...........................
ViewBag.Created = 1;
}
Controller 2 which renders 2nd partial view:
public PartialViewResult Index(int createdId)
{
return PartialView(new List<Model2>());
}
Regarding View 1 cannot be found, is because the keyword return in your second Create action is missing. The button click submits the form to the Create method with [HttpPost] attribute and the end of the method, it needs a return View.
Reg Any tips on passing this model object successfully to the other view please, The return in the second Create method should be return View(model); and not 'return View(new MyModel);` as later on in the View you are going to use the Model.
Re I put id=1 and tested it and the same error occured., because runtime never reachs that point as the operation is being handed to '[HttpPost] Create' and it never get back to your Original Page.
There are other issues with your code as you are using different names in your code than what you mention in your description...
A simple solution is:
1- use the following return at the end of you [HttpPost]Create Action:
return RedirectToAction("Action2", "Area/Controller2", new { id = model.Id});
2- replace the following code in your initial page
if (ViewBag.Created ==0) {
#Html.Partial("CreateView1",Model);
}
else
{
{ Html.Action("Action2", "Area/Controller2", new { id = Model.Id }); }
}
with the following:
#Html.Partial("CreateView1",Model);
and remove anywhere you set ViewBag.Created = 0 or ViewBag.Created =1
I also assume the action action2 in controller Controller2 returns a valid Partial View.
Hope this help you get some idea to fix your code.
You may have omitted this for brevity, but you will want to return a viewresult at the end of your post action:
return View(new MyModel());
try this:
if (ViewBag.Created ==0) {
#Html.RenderPartial("CreateView1",Model);
}
I'm working on an MVC3/Razor page, and in my _layout I have
#RenderSection("relatedBooksContainer", false)
In another page I use that section with:
#section relatedBooksContainer
{
#{ Html.RenderPartial("~/Views/Shared/Bookshelf.cshtml", Model.Books);}
}
This doesn't work. From what I've read, RenderSection will only ever go one layer deep - it has no concept of the Html.RenderPartial in the related section and will just return a blank area. The workaround I read at http://forums.asp.net/t/1590688.aspx/2/10 is to use RenderPage and commit the returned HTML to a string, then outout that string in the render section...which works! That is, until I pass a model to the partial page, then it throws an error saying:
The model item passed into the
dictionary is of type
'TheBookshelf.ViewModels.BookshelfViewModel',
but this dictionary requires a model
item of type
'System.Collections.Generic.List`1[TheBookshelf.EntityModel.Book]'.
Anyone have any idea why this might be happening? Are there any other ways to achieve this?
Try the #Html.Partial instead
#section relatedBooksContainer
{
#{ Html.Partial("~/Views/Shared/Bookshelf.cshtml", Model.Books);}
}
The error message is regarding the type and return type of the Bookshelf from the model.
public IEnumerable<Book> Bookshelf()
{
var q = from book in bookshelf
select book;
IEnumerable<Book> myBooks = q.ToList<Book>();
return myBooks;
}
did the solution in the provided link work for you?
I couldn't get it to work. That is I couldn't get ViewData["MainView"] to pass the data from Layout.cshtml to partialview. This aparently is a feature as every view is supposed to have it own ViewData obj. It seems ViewData is not global like I have thought. So what I get in ViewData["MainView"] from Layout in my partial view is null......I eventually found a work around for this and was able to pass the page reference from Layout to Partialview via a #Html.Action call from Layout -> Controller -> PartialView. I was able to get my partialview to access and write to the correct rendersection. However I want to call the same partialview many times in my Layout.cshtml. A subsequent call to the same Partialview again in the Layout, does not work, as the reference to layout has changed since the first call and rendersection update. So the code looks like this:
Layout.cshtml:
#RenderSection("Top", false)
#Html.Action("Load", "Home", new { viewname = "_testPartialView", pageref = this })
#Html.Action("Load", "Home", new { viewname = "_testPartialView", pageref = this })
Partial View:
#Model Models.testModel
#Model.Content
#{
var md = (System.Web.Mvc.WebViewPage)#Model.pageRef;
#*This check fails in subsequent loads as we get null*#
if(md.IsSectionDefined("Footer")) {
md.RenderSection("Footer");
}
else {
md.DefineSection("Footer", () => { md.WriteLiteral("<div>My Contents</div>"); });
}
}
}
controller:
public ActionResult Load(string viewname, System.Web.Mvc.WebViewPage pageRef)
{
var model = new Models.testModel { Content = new HtmlString("time " + i++.ToString()), pageRef = pageRef };
return PartialView(viewname, model);
}
I hope I am able to put this question together well.
In a partial view I have a link to a create action:
public ActionResult CreateProject()
{
return View("EditProject", new Project());
}
Now this loads another view which allows editing of the blank model passed to it. But when form is submitted it is supposed to post to:
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult EditProject(Project record)
{
if (ModelState.IsValid)
{
projectRepo.saveProject(record);
return View("Close");
}
else
{
return View("EditProject");
}
}
This method works for many of the tables and edit actions work just as well for the same view. But only for the create action (with the blank model) the form keeps calling to the create action, as I traced with the debugger.
One of my team mates has solved this problem so:
[AcceptVerbs(HttpVerbs.Get)]
public ViewResult EditProject(int id)
{
Project project = null;
if (id == 0)
{
project = new Project();
}
else
{
project = (from p in projectRepo.Projects
where p.ProjectID == id
select p).First();
}
return View(project);
}
And in the partial instead of having <%= Html.ActionLink("Create New", "CreateProject")%> there'd be <%= Html.ActionLink("Create New", "CreateProject", new { id = 0 })%>.
Now I was hoping to find out why the previous method would not go through, since it does for other tables in other views. Thanks.
By default your form will post to same URL it was rendered at. Since you called create action it will post back to create action, and not edit, 'cos views do not matter (-:
Explicitly use
<%= using( Html.BeginForm("Action","Controller) ){ %>