I am currently working on an ASP.NET MVC web application using DevExpress controls and I ran into a very annoying issue that I could not fix so far.
I am implementing a page/view which consists of multiple partial views. One of those partial views contains a DevExpress GridView control which contains a so called "DetailRow". This detail row is meant to show additional information about a row when clicking on a small "+" button on the left side of each row. I already use a very similar (basically almost identical) GridView inside of a DevExpress "PopupControl" on another page of my website without any problems, but on the new page I am currently working on it just does not work.
The page actually loads just fine when I open it, but as soon as I click on the small "+" in a row my controller's Index-method is called and I do not understand why. On the other page which has the GridView inside a PopupControl, only the method for the partial which contains the GridView and the method for the actual content of the DetailRow is called, which is what I would expect to happen on my new page as well.
I have already recorded the network communication between the site and the server and I do not see any GET request either which would result in the Index-method getting called. There is only a POST for the partial which contains the GridView. I also get the following DevExpress-specific error logged in the console when this happens:
Invalid server response. It is required that a Partial View contains
only the extension definition code, without any additional markup. To
learn more, see https://www.devexpress.com/kbid=KA20010.
Unfortunately the linked article in that error did not help me figure out the problem either. It talks about making sure that all extensions are defined in a separate PartialView with no extra tags but I already have it like that, there are no extra tags anywhere in my partial views. I also do not assign a unique SettingsBase.Name value so that cannot be the problem either.
Does anyone know what is going wrong here or how I can further debug the problem? I do not know any way of finding out why the Index-method of my controller is being called so I have no clue what to do.
I just managed to find the solution for my problem. There was something wrong with my routing so the POST request I mentioned in my question was routed to the wrong controller. I fixed the routing and now everything works as expected.
Related
I feel like this should be obvious, but I'm stumped. We're running Sitecore 7.1 with MVC.
There is a Header rendering that includes conditional logic depending on the status of Sitecore.Context.IsLoggedIn. Works fine.
There is a second rendering that either allows the user to log in OR displays account information. When the [HttpGet] acton is called, the controller checks IsLoggedIn and returns one of two views. When the [HttpPost] action is called (i.e. when the user logs in), The controller calls AuthenticationManager.Login() and then returns the view with the account info. Works fine.
It's a simple solution that allows us to place one rendering on the page, and it works great, except for one thing: the header rendering still shows the not-logged-in content immediately after logging in.
Caching is turned off on the header rendering and in the presentation details. When any link is clicked or the page reloads, the header updates to show the correct info. The problem is only after the initial request/response, when the login form submits and returns an alternate view. Although we've had a complete HTTP request/response cycle, it's like Sitecore doesn't bother to check anything except the rendering that was directly affected.
I know I can solve this by returning a hard Redirect() after logging in but that seems inelegant and creates annoyances, like losing ViewBag info.
What I am really looking for is a way to tell Sitecore, "hey, refresh that other rendering!"
The fact that I can find nothing at all on-line about this 'problem' tells me I might be doing something conceptually wrong.
As I see it there are two ways of handling this problem:
FormHandler
You use #Html.FormHandler to specify a Controller and an Action to handle the authentication. The FormHandler action will execute very early (see: https://twitter.com/dmo_sc/status/480001473745399809) in the page execution, before anything is rendered, and all your Renderings will have the same view of whether users are logged in or not.
Martina did a good writeup on Sitecore MVC and forms:
https://mhwelander.net/2014/05/28/posting-forms-in-sitecore-mvc-part-1-view-renderings/
https://mhwelander.net/2014/05/30/posting-forms-in-sitecore-mvc-part-2-controller-renderings/
Post-Redirect-Get
I really want Sitecore MVC to have this feature build in, as it is useful for all form submission scenarios (bar AJAX). The idea is to handle the POST request and work out what you want to respond (and store this in tempdata). Instead of returning a ViewResult you issue a redirect to the same URL, this forces a GET to the page (at this point all the logged in state is same for all Renderings) where you fish the result out of tempdata. Also P-R-G protects against resubmitting POST requests.
cprakash documented his experience doing P-R-G:
https://cprakash.com/2015/01/12/sitecore-mvc-form-post-simplified/
Off Topic: Multiple forms on single page
This will not solve the OP problem, but worth having a look at in this context:
http://reinoudvandalen.nl/blog/ultimate-fix-for-multiple-forms-on-one-page-with-sitecore-mvc/
In MVC, your renderings are executed sequentially, top to bottom. So if your header rendering comes before the login status rendering, it's going to be done before the user is logged in.
The elegant way to do this would probably be to do your post and update both elements via JavaScript. If you want to keep the header logic separate from the login status logic, your login status script could allow other components to register their own callbacks. You could even build out a client-side message bus, if you will be doing this sort of thing frequently.
You could take a look at Jeremy's approach:
https://jermdavis.wordpress.com/2016/04/04/getting-mvc-components-to-communicate/
The key takeaway, I think, is where he switches the order of the placeholders by placing the results into variables and then render them wherever you want them.
#{
HtmlString main = Html.Sitecore().Placeholder("MAIN");
HtmlString head = Html.Sitecore().Placeholder("HEAD");
}
<head>
#head
</head>
<body>
#main
</body>
I have code in place to disable caching in my MVC application. I'm using the following response headers. They seem to work in all browsers except for Chrome (currently using version 31.0.1650.48). Users are able to submit a form with model values. When they hit the back button I need the page to reload with a blank model. The headers appear to partially work since the request is hitting the action and returning the blank model. However the view isn't updating. The values from the previous post are being retained. I've tried clearing the ModelState but that doesn't work. Any suggestions? Thanks in advance!!
filterContext.HttpContext.Response.Cache.SetExpires(DateTime.UtcNow.AddDays(-1))
filterContext.HttpContext.Response.Cache.SetValidUntilExpires(False)
filterContext.HttpContext.Response.Cache.SetRevalidation(HttpCacheRevalidation.AllCaches)
filterContext.HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache)
filterContext.HttpContext.Response.Cache.SetNoStore()
Turning off autocomplete for the form fixed this for me. I appreciate all the input!
<form autocomplete="off"></form>
There is a way to do this in javascript for everything in one go like so...
document.getElementById("YourFormID").reset();
Just add an id to your form and all your inputs will reset on page load. Regardless if its a first time visit or a back button click with the page being cached. The biggest difference from your solution and this is that "the autocomplete attribute is new in HTML5". Which means it is not supported in older browsers, and though it does what you want it also prevents the user from autofilling fields. Meaning that for example on text types inputs users will not see a suggestion of words they may have entered on previous or other pages. You can see an example here.
I have quite a big application, sometimes with pretty complicate data being created by the user (on the way to the database the data is being altered a lot). The issue is, that any time I need to alter the code, I get stuck for quite a few hours before finding the problem.
Actions in my app:
User opens the jquery modal dialog
There is a form in the modal dialog
User alerts the data and saves it
About app:
The application contains of one site with a table and several buttons
Each of these buttons open a different modal dialog
Each form submission is handled via ajax -> cakephps this->js->submit
How I wrote the code:
For each modal dialog I created an element
After clicking the button I open the element as a jquery modal dialog
Lots of these modals gain information via for example: "On click/on double click etc" events.
My problem:
Every time I alter the cakephp code which is called by $this->Js->submit I feel like putting a gun to my face and pulling the trigger.
I dont know of any easy way of how to debug variables in these functions (cakephps debug doesnt show anything ofc -> the view of those ajax/php functions are not in the main site)
Dont know if firebug has any features for debugging php, but I dont know of any.
The only thing that works for me a bit is commenting out lines of code and putting an alert in the success like this to maybe sometimes get to the values, but it doesnt feel right.
Being used to write code in c++/java and printing or debugging with breakpoints makes me frustrated, when I use such a modern programming language and try to guess out where the bugs might be..
Most errors:
Mostly null pointers or checking !isset index being accessed, but since I know of no way of printing these errors from modals no checking on the indexes helps me.
Use FirePHP it is a great enhancment of firebug. Works well.
I'm building a web application that has a particular model representing some events. Users need to be able to add N number of people to a given event. Choosing people is handled by a partial view.
I'm trying to build a menu that displays when users click "add a person" to the event. Because the event hasn't been filled out completely yet, there is nothing in the database to persist between requests.
I also have validation logic on the event page.
My proposed solution is to add the form to search or add for people on the event form itself and have a submit button that sends the values that have been added back to the server, where I can store them in ViewData or Session.
Unfortunately, doing this flags the validation.
My second solution is to load a partial view responsible for loading the UI to add/search for a person. I could add a little code on the method in the controller that returns a partial view storing the existing data in a session variable or viewdata. Trouble is, I have to submit the form to do it--again tripping the validation!!!
I'm wondering if perhaps I chose the wrong tool to do this...because in webforms, there would probably be a postback and you would just perform an operation on that postback. I'd like to avoid rewriting the application in webforms and am wondering if there are ways I'm overlooking in ASP.NET MVC.
Thanks in advance for the ideas!
I would probably have the partial view send it's data to the main page (with javascript). That way there is only one post to the server and it is when all of the data the user needs to enter has been filled out. How are you displaying the partial view? Is it on the main page (in a div), or is it a separate pop-up window? Either way, you should be able to use javascript to store this data on the main page and post all of the data back at one time.
HTH
Hello stackoverflow world.
(This is the first time I actually post a question here. Exciting)
A while ago I inherited a 2 year old MVC website from one of the teams within my corporation. I know most the ins and outs of this solution now but there is something strange cropping up in my error logs which I do not understand.
Every now and then I will get an error messages like this one:
A public action method 'xyz.gif' could not be found on controller MyNamespace.MyController
What I don't understand is WHY is this action (a gif image) being called in the first place?
I've seen 2 different gifs in the error logs pageerror.gif and refresh.gif
As this is an inherited solution I double checked everything and made sure that there are in fact no images like that in the project and no reference anywhere even to those words in the controllers, views, style-sheets or even in the source of pages within the same controller.
I seriously doubt that the users are playing around with the URLs and adding random gif names to them to see what happens.
I'm all out of ideas. Anyone out there who can suggest more places to look for the culprit?
Ta!
As Tchami pointed out in a comment on the original question, this is related to Internet Explorer's default error pages.
As I have set up custom error pages I believe this is either due to an internal server error or possibly somehow an action cancel error from the client side, i.e. client side error. I can't be 100% at this point.
The question is not fully answered but I mostly know what the cause is now.
From my point of view I've identified that I need to improve this ASP.NET MVC application so that
1) it doesn't report/log errors when someone tries to navigate to a non-existing controller action (e.g. these refresh.gif actions or any other)
and 2) handle it better for the client so that they don't end up clicking from one error page (default IE error page) to another (my custom error page when clicking the refresh icon on the IE page)
Another stackoverflow thread on a related topic:
Significance of 'pagerror.gif'?
(i can't post more links as I'm a new user)
CHEERS!
Solveig
Can you get the error to show up in the logs when you use the site yourself? If so, an add-in such as HttpWatch might help you see those .gif requests. If you can understand more about when they happen you might be able to figure out what's going on.
Pagerror.gif and refresh.gif are the default images from the IE browser/IIS server. Normally these images were shown when the browser is not able to retrieve the content.
If you see these errors in logs, then check the iis log to get more information.
For example,
IIS Log : look for this feild ,
cs(User-Agent)
compatible;+MSIE+6.0;+Windows
Here few things to be noted,
1)IE 6.0 apparently makes these requests on its own. I am not sure if any other IE 6+ Browser would show similar behavior.
2)All this will do is generates a 'bogus" event log entry because a null reference exception could happens when you request a non-existing GIF and that request goes through MVC pipeline.
3)Technically this simply can be ignored.
4) Optionally we could check if through routing we could stop “.gif” files from being processed by MVC Pipeline
All i would suggest is to handle it gracefully.
It may be difficult to pinpoint this, but my thought would be: check the javascript. If the image name is being dynamically generated somewhere, and then requested, a simple "find and replace" may miss the reference.