ASP.NET MVC. Specific URL for partial views - asp.net-mvc

I'm new to ASP.NET MVC. So my question may seem to be little bit naive. Anyway I've spent hours searching for any information on my topic, but no result. So I would be very grateful for your help.
So this is my problem.
In my Index view I have a div, where I put contents of different Partial Views depending on the link that user clicks.
Here's the code.
Index.cshtml:
<div id="dynamicContent"></div>
About Cbsr Agent
Application Areas Of CBSR
JavaScript:
function updateContent(contentUrl) {
$.ajax({
url: contentUrl,
type: "GET",
success: function (data) {
$('#dynamicContent').html(data);
}
});
}
Controller:
public class AgentController : Controller
{
//Index action
public ActionResult DynamicContent(string name)
{
return PartialView(String.Format("Partial/" + name));
}
}
So, everything works fine. When user clicks the link, the appropriate partial view is loading into the div.
The problem is that in adrees bar of a browser i get the following URL: example.com/Agent# whatever link i click.
So my question: Is there any way to generate the unique URL for each partial view? For example: example.com/agent/partial/AboutCbsrAgent. And is it possible to make so that when I paste this link into the browser's address bar, the whole view and NECESSARY partial view will be displayed?
Thank you in advance for your help!

You can create two separate actions in your AgentController, for the two URLs, and pass name of the partial view you want to render. Something like:
public ActionResult AboutCbsrAgent()
{
ViewBag.MyPartialView = "AboutCbsrAgent";
....
return View("Index");
}
Then in your Index.cshtml:
<div id="dynamicContent">
#Html.Partial(ViewBag.MyPartialView)
</div>
You'll probably need to adjust the paths, but you get the idea.

If you want to avoid the # in your url use:
About Cbsr Agent
If you know your users are mainly FF, Chrome, IE9 <, or you don't care if the browser doesn't support it, you can use history.pushState
Although you will still have to find a solution for loading the correct content if the user revisists that url (with pushState)

Related

MVC controls not working properly without page refresh

I've got an MVC controller that can be called via form submission in a couple different places. The controller then renders a view whose primary purpose is to allow the user to send the document or post it to an external site, as well as fill in text fields that will be used in the notification email.
I am performing validation on these fields - the user can enter custom subject/body text. If they do not, they will receive a popup alert and can either return to the form or submit it using default text indicated in the placeholder value.
The problem is that when the user first reaches this page and clicks the send button, no input in the textboxes is actually registering and it gives the empty string notification regardless of what is actually in the fields; however, if I hit F5 and try again, the input works perfectly.
I feel like this has something to do with the form submissions that initially call this controller being done via POST action, whereas it seems to work fine with the GET on page refresh. I just can't figure out how to either get the content to respond properly when the controller is called via POST, or how to submit the form without posting the data.
Thanks in advance for reading and any help.
Here is the calling controller:
public ActionResult Index(FormCollection collection)
{
//modelbuilding code
return View (Model);
}
The code that calls the controller always uses this format: (in this case, it would be called from the Recipients/Index view.
#using(Html.BeginForm("Index", "Distribution", FormMethod.Post )) {
//form values
<input type="submit" data-role="button" value="Done"/>
}
Here is the relevant part of the view and the JS validation function:
<div id="SubjectTemplate">
<p>Subject: <input id="emailSubjectTextBox" name="EmailSubject" placeholder="#EmailSubject" /></p>
</div>
Send Notification
<script>
function validateInput() {
var possibleErrors = [];
if (!(document.getElementById('emailSubjectTextBox').value)) {
possibleErrors.push('#incompleteEmailSubject' + '\n');
}
//more validation that works the same way and has the same problem
if (possibleErrors.length > 0) {
if (confirm(possibleErrors))
{
window.location.href = '#Url.Action("Send")'
}
}
else {
window.location.href = '#Url.Action("Send")'
}
}
</script>
I'm not sure I fully understand your question, but generally speaking you should not use the same action for POST and GET.
Even more importantly, you should not be using POST if your action does not have some kind of side effect. If all you are doing with your form submission is making some kind of choice then you should be using GET.
See the following post for more information and examples of how to perform ajax GET requests using jQuery: http://www.jquery4u.com/ajax/key-differences-post/
Regardless of what you are trying to do, it is very good practice that POST calls perform some action, and then redirect to a GET action which returns to the user.
[HttpPost]
public ActionResult Index(FormCollection collection)
{
//do whatever you need to save the record
return RedirectToAction("Index")
}
[HttpGet]
public ActionResult Index()
{
//modelbuilding code
return View (Model);
}
Not only does this help your controller adhere to a RESTful methodology, it also stops the user getting that annoying 'Are you sure you want to resubmit this page' if they happen to press f5
Hope this helps.
I found the problem resulted from jQueryMobile automatically utilizing AJAX to post forms. I solved this by including new {data_ajax = "false"} to the Html.BeginForm statements.

I need some clarification on GET and POST concerning JQuery AJAX and MVC 3

I am wondering if it is an all-or-nothing situation. What I would like to do, Load (GET) my page by normal MVC 3. Controller takes Model and passes it to View. View and Razor render it. However, when I post back, I'd like it to postback the selected info through AJAX. Is this possible? Or do I have do GET and POST with AJAX?
You can certainly POST using AJAX after GETting using other means.
Here's a random question on SO that does just this:
Ajax post in MVC 3 with multiple-form View
The GET and POST actions do not have to be related at all.
Try something like the below.
Controller Code:
[HttpGet]
public ActionResult WhateverActionName()
{
YourViewModel yvm = new YourViewModel();
//Initalize viewmodel here
Return view(yvm);
}
[HttpPost]
public ActionResult WhateverActionName(YourViewModel yvm)
{
if (ModelState.IsValid) {
RedirectToAction("OtherAction", "OtherController")
}
return View(yvm);
}
Ajax:
$.ajax({
url: myurl
// processData: false, // you may need this option depending on service setup
success: function(){
location.href = "TARGET LOCATION";
},
type: "POST"
});
For target location: You're going to need to feed the ajax a variable containing whatever URL the following generates
#URL.Action("Action", "Controller")
http://knockoutmvc.com offers an nice way of integrating server side code with client side and it looks like it might help you easily achieve what you want.

MVC and JQuery UI Tabs - How do I anchor to tabs from various actions?

I have a details view for courses. On that view, I have a lot of information, so I broke it up into nice JQuery UI Tabs sections and everything is great...except...
Some of the tabs have forms on them. For instance, upload course materials, add tasks, edit rosters, etc... after I submit any of the forms, I want to perform the action on my controller and then redirect to the details view again, only this time I want to be anchored to the tab that I was on before I submitted. According to the Tabs documentation, it's just as simple as adding #tabs-4 or #tabs-n to the end of the URL, but I'm not sure how to tell my controller how to do that...
so if one of my form's controller action is (simplified)
public ActionResult CreateTask(Task task)
{
db.Add(task);
db.Save();
//I want to go to /details/id + #tabs-4. How?
return RedirectToAction("Details", new { id = task.CourseID });
}
and then details is (simplified)
public ActionResult Details(int id)
{
Course course = db.GetCourse(id);
// How do I tell the view to open #tabs-4 or 3 or 2??
return View(course);
}
Additionally, I'd like to have other methods that redirect to the same details view, but instead give it a #tabs-3, #tabs-2, etc, so I assume I have to set that up in the first method, and pass it to the details action.
var url = Url.RouteUrl(new { action = "Details", id = task.CourseID });
return Redirect(url + "#tabs-4");
You can use UrlHelper.GenerateUrl method, passing your anchor as fragment.
I would add an extension method to UrlHelper to wrap a call to GenerateUrl, as it takes 10 parameters and you do not need to provide all of them manually in all the cases.

how to call controller from button click without using ajax mvc

I'm new to web programming in general so this is probably a really simple question. I couldn't find anything on the web however.
What I want to do is call my controller with the typed search string and return the results from a database and paginate the results. Right now I am using a function that is called when the button is pressed. The function looks like so:
function SubmitSearch() {
var searchBox = document.getElementById('searchBox');
var searchButton = document.getElementById('SearchButton');
$.post("MyController/MyAction/",
{
searchString: searchBox.value,
page: null
}, function(result) {
$('#searchResults').html(result);
searchButton.value = "Search";
});
}
What happens is my controller is called, and my searchResults div is populated with the results and paginated. The user can click any search result returned to view the details.
The problem is when the user clicks the browsers 'back' button, the page returns to the state before the search was entered, and this is because of the ajax call. What I want to do is, call the controller and have the page load like google would. Instead of using a PartialView, I would use a View (my guess).
How would I call the controller and have the page RELOAD with the results. I must be missing something fundamental because this definitely seems like it should be easy.
If you don't want to use AJAX then you need to place your text field in a form element on your page, something like:
<form action="MyController/MyAction/" method="get">
<input id="SearchBox" name="SearchBox" type="text" />
<button type="submit">Search</button>
</form>
Then in your controller return the view with the list of results.
You probably also want to look into RESTful URLs and the PRG (Post, Redirect, Get) pattern to maintain the integrity of the back button and enable correct bookmarking of pages etc.
I think you might actually be looking for an AJAX History library to help when the Back button is pressed rather than altering your app. Take a look at this blog post.
Aspx:
<% using (Html.BeginForm<MyController>(m => m.MyAction(null)) { %>
<%= Html.TextBox("q"); %>
<% } %>
// Listing
Controller:
public class MyController : Controller
{
public ActionResult MyAction(string q)
{
var repository; // instance of your repository.
if (String.IsNullOrEmpty(q))
{
return View(repository.GetAllBlogs());
}
return View(repository.SearchBlogs(q));
}
}

ASP.NET MVC - Go to a different view without changing URL

is it possible to go to a different View without changing the URL? For example in my Index View, I have a link to go the the Details View but I would like to keep the URL the same.
Thank you very much,
Kenny.
As already mentioned, you could make the Details link an Ajax.ActionLink and use this to change the content of a div.
Failing that, the only other way I can think of doing it is by making your details link a button and POST to your index action. You could apply CSS to the button to make it appear more like a normal html link.
public class HomeController : Controller {
public ActionResult Index() {
return View("Index");
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Index(int hiddenInputFieldId) {
return View("Details");
}
}
EDIT:
Based on JonoW's comment, you'll have to pass in a 'fake' param with your post, this is not really a problem though, you can just use a hidden input field for it.
You can return the same view from multiple controller actions, but each controller action requires a unique URL:
public class HomeController : Controller {
public ActionResult Index() {
return View("home");
}
public ActionResult About() {
return View("home");
}
}
If you want a link to load up content from a different page without changing the URL, you'll have to use some Ajax to call the server for the content and update the parts of the page you need to change with the new content.
I don't know why you would like to do that, but you could have an Ajax.Actionlink which renders the Details View..
There is almost no reason to hide an URL, not sure what you would like to to.. maybe you explain further that someone can give a better approach.
You can use a good old Server.Transfer for this. However, I'd suggest doing it like has been detailed in this SO post. This gives you an easy way to return an ActionMethod from your current action without peppering your code with Server.Transfer() everywhere.
You can do this by rendering partials- I do this to load different search screens. Sample code is as follows (this is slightly different to my actual code, but you'll get the idea):
<% Html.RenderPartial(Model.NameOfPartialViewHere, Model.SomeVM); %>
Personally though, I don't see why you don't just change the URL?

Resources