How do i improve the legacy code implementation, Response.Redirect? - asp.net

Some scenarios to ponder. There is a legacy code which has following implementation Example1 and Example2. If we try to implement MSDN recommendation then the legacy code fails.
Here is a Legacy code example:
Example 1:
void Page_Load() {
.... some code
if(condition) {
/// some condition
} else {
RedirectPage(url);
}
// another code block
// some other conditions.
}
Example 2:
a. File1.ascx
void Page_Load() {
try {
.. some code
base.CheckPreference();
RedirectPage(defaultPage);
}
catch(Exception ex) {
ExceptionHandling.GetErrorMessage(ex);
}
}
b. BaseClass.cs // this is the base class
void CheckPreference() {
try {
if(condition) {
RedirectPage(url1);
} else if(condition2) {
RedirectPage(url2);
} else {
// update session
}
}
catch(Exception ex) {
ExceptionHandling.GetErrorMessage(ex);
throw;
}
}
void RedirectPage(string url) {
Response.Redirect(url);
}
One possible way is to add a boolean field in the class e.g endExecution, set the field to true whenever RedirectPage is called.
We have to update RedirectPage code see code snippet below:
// Updated code - MSDN recommendation.
void RedirectPage(url) {
Response.Redirect(url, false);
this.Context.ApplicationInstance.CompleteRequest();
endExecution = true;
}
Please suggest some other better ways to improve the legacy code implementation.

Probably the most unintuitive thing for folks issuing a redirect is that in our minds we've already returned from the method what we call Respond.Redirect (or whatever the equivilent is in your language/platform of the day. All we've done is call a method.
Bottom line is that you have to stop processing the request to avoid trying to commit to responses for the same request. That would throw an exception on just about any platform I've worked with.
ASP.NET MVC improved this with the ActionResponse so that you are returning from the method (and terminating the remainder of request processing) with code that looks like this:
return Redirect(url);
Bottom line is that you need to get in the habit of returning from your event right after you perform your redirect. Any deviation from that habit needs to be documented in the code why. This will help make the application perform the way you expect.
The approach that you've taken is perfectly reasonable.

Related

Change the POST method to DELETE

I built a servlet with jersay and in the Initially of the project all my fuctions was written with POST or GET only. I want to change the metoud to DELETE and PUT in respectively.
this is the old situation(that work well):
#POST
#Path("removeCompany")
#Produces(MediaType.TEXT_PLAIN)
public Response removeCompany(#QueryParam("id") long id) {
try {
getFacaed().removeCompany(id);
} catch (SystemMalfunctionException | CompanyNotExistsException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
return Response.ok("Company successfully deleted").build();
}
I would like to change this situation:
#DELETE
#Path("removeCompany")
#Produces(MediaType.TEXT_PLAIN)
public Response removeCompany(#QueryParam("id") long id) {
try {
getFacaed().removeCompany(id);
} catch (SystemMalfunctionException | CompanyNotExistsException e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
return Response.ok("Company successfully deleted").build();
}
In the old situation everything work well but when I change the method to DELETE I get this error :
Of course I keep the changes, restarts the server and restarts the project.
editation:
if I change the method in postman from DELETE to POST its work although in the code It is noted that the method is DELETE.
Perhaps this will help to understand the problem.

Best place to load data when navigating XamarinForms Prism 6?

One of the cool features in Prism 6 is the deep linking and passing parameters. In a lot of cases, you'd want to use this parameter to look up data from a web service. Ideally this would be using async/await to get the data. Where is the best place to do this? The OnNavigatedTo method for example is a void.
Although I don't have a case for Deep Linking yet, I am doing many loads on many pages inside OnNavigatedTo and it is working great!
Here is a sample:
public void OnNavigatedTo(NavigationParameters parameters)
{
if (parameters != null &&
parameters.ContainsKey("MyKey"))
{
SomePrivateFieldInViewModel = (YourVariable)parameters["MyKey"];
//SomeWork
}
GetItems();
}
private async void GetItems()
{
try
{
SomeListInViewModel = await WebServices.GetEntity(SomePrivateFieldInViewModel);
//SomeWork
}
catch (Exception ex)
{
//SomeWork
}
}

jsf2 spring webflow transition exception handling does not work with exceptions during render phase

I am not sure either I missed a point in the concept of exception handling in webflow, or this is a bug.
I hope someone can help me to understand it, or I will file a bug in webflow/spring mvc.
Following situation.
JSF2 (2.1.X) with webflow 2.4.0 and spring faces (2.4.0)
A RuntimeException is thrown during render phase. Not nice, but can happen.
Exceptionhandling kicks in, a it tries a make a new tansition to an error site. Works like expected.
ErrorState is resolved, it tries to make a transition to it. Everything is ok so far. Now here is the problem. The transition will never be executed.
org.springframework.webflow.engine.ViewState
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
context.assignFlowExecutionKey();
ExternalContext externalContext = context.getExternalContext();
if (externalContext.isResponseComplete()) {
if (!externalContext.isResponseCompleteFlowExecutionRedirect()) {
clearFlash(context);
}
} else {
if (shouldRedirect(context)) {
context.getExternalContext().requestFlowExecutionRedirect();
if (popup) {
context.getExternalContext().requestRedirectInPopup();
}
} else {
View view = viewFactory.getView(context);
context.setCurrentView(view);
render(context, view);
}
}
}
Transition will only be done if the response is not already completed.
This will never happen for any exception in the render phase, because in
org.springframework.faces.mvc.JsfView in the finally block there will be always a responseComplete.
/**
* Performs the standard duties of the JSF RENDER_RESPONSE phase.
*/
public void render() throws IOException {
FacesContext facesContext = FlowFacesContext.getCurrentInstance();
if (facesContext.getResponseComplete()) {
return;
}
facesContext.setViewRoot(this.viewRoot);
try {
logger.debug("Asking faces lifecycle to render");
this.facesLifecycle.render(facesContext);
} finally {
logger.debug("View rendering complete");
facesContext.responseComplete();
}
}
For me it looks like a bug. How is the webflow exceptionhandling to work with exceptions in the renderphase?
There is no way to change the responseComplete-Flag, in org.springframework.webflow.context.servlet.ServletExternalContext
It is a private field with only the possibility to set it to true via
public void recordResponseComplete() {
responseComplete = true;
}
I changed in the debugger-session the flag to false. Then everything works like expected, and the user sees can see the error page.

Custom error handling in webmethod returning XmlDocument

I'm working with a client who has a web method like this:
[WebMethod]
public XmlDocument Send(string stuff)
{
// ...
}
At present, there's a class of exceptions which occur which the code is re-throwing, triggering ASP.Net's standard handling of exceptions.
We'd like to change it so that the webmethod still returns status code 500, but with some text/plain diagnostic information we provide rather than the default ASP.Net stuff.
What's the appropriate way to do that?
I've made it work, using Context.Response.End like this:
[WebMethod]
public XmlDocument Send(string stuff)
{
try
{
// ...normal processing...
return xmlDocument;
}
catch (RelevantException)
{
// ...irrelevant cleanup...
// Send error
Context.Response.StatusCode = 500;
Context.Response.Headers.Add("Content-Type", "text/plain");
Context.Response.Write("...diagnostic information here...");
Context.Response.End();
return null;
}
}
But that feels hacky, so I'm hoping there's a better answer.
But that feels hacky, so I'm hoping there's a better answer.
It feels hacky because it is hacky.
The better answer is: Return XML, like you said you would, with whatever information it is you want to include. The service returns XML, it was intended for code, not people, to consume.
[WebMethod]
public XmlDocument Send(string stuff)
{
try
{
// ...normal processing, creates xmlDocument...
return xmlDocument;
}
catch (RelevantException)
{
// ...irrelevant cleanup...
// ...error processing, creates xmlDocument...
Context.Response.StatusCode = 500;
return xmlDocument;
}
}

SEAM: Component "disinjected" "too soon" in interceptor?

Let's say I have the following interceptor in a SEAM app:
public class MyInterceptor {
#In
private Monitor myMonitor;
#AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
try {
myMonitor.a();
return ctx.proceed();
}
finally {
myMonitor.b();
}
}
}
myMonitor.a() works (so Monitor is correctly injected), myMonitor.b() fails because Monitor is already null. Seam Doc says: "Injected values are disinjected (i.e., set to null) immediately after method completion and outjection."
Is that what is happening? Can I do something to tell SEAM to "not yet" "disinject" the component? I can of course also do something like XContext.get(..), but I'm wondering whether this is a bug or a mistake from my side. thanks!
Try this one instead
Object response = null;
try {
myMonitor.a();
response = ctx.proceed();
} finally {
myMonitor.b();
}
return response;
regards,
Avoid using injection.
Try working around this problem. I see you have some sort of monitoring going on. Look at this interceptor that captures the amount of time a method is executed in Seam components. Try modifying your code to match that.
It works great!
Here is the link
Seam is working as advertised.
You could just ignore the disinjection:
public class MyInterceptor {
private Monitor myMonitor;
#In
private void setMonitor(Monitor aMonitor) {
if (aMonitor != null) {
myMonitor = aMonitor;
}
}
#AroundInvoke
public Object aroundInvoke(InvocationContext ctx) throws Exception {
try {
myMonitor.a();
return ctx.proceed();
}
finally {
myMonitor.b();
myMonitor = null; //perform disinjection yourself
}
}
}
The caveat here is that Seam is disinjecting the reference for a reason. Seam wants to control the lifecycle and identity of "myMonitor" and by keeping a reference to it, you are not abiding by your contract with Seam. This could lead to unexpected behavior.
For instance, if myMonitor were for some reason in the Stateless scope, Seam might destroy it before ctx.proceed() returns, leaving you with a reference to a broken proxy. Best advice is to know the scope and lifecycle of what you are retaining since you are "living on the edge."

Resources