The localhost page isn’t working. localhost redirected you too many times - asp.net

I got a problem when debugging my MVC program and I want to acces to my db called "UserActivity".
on the browser, it saying that "The localhost page isn’t working
localhost redirected you too many times."
but without showing the specific error location.
here is my UserActivtyController, GET /UserActivity/Index code:
public class UserActivityController : BaseController
{
//GET /UserActivity/Index
public ActionResult Index(string returnUrl, int page = 1, string sort = "Id", string sortDir = "ASC", string filter = null)
{
String query = #"
SELECT Id
,CreatedBy
,CreatedOn
,ModifiedBy
,ModifiedOn
,ContactId
,EntityName
,EntityId
,ActivityType
,ActivityStatus
,DueDate
,ActualEndDate
,MasqueradeOn
,MasqueradeBy
FROM UserActivity
-- ORDER BY CreatedOn DESC
-- OFFSET (#PageNumber -1) * 30 ROWS
-- FETCH NEXT 30 ROWS ONLY
";
//string countQuery = #""
List<UserActivityModels> userActivity = null;
using (IDbConnection db = new MySqlConnection(ConfigurationManager.ConnectionStrings["CRMPORTALSQLCONN"].ConnectionString))
{
userActivity = (List<UserActivityModels>)db.Query<UserActivityModels>(query, new
{
#PageNumber = page,
});
/*ViewData["TotalCount"] = (int)db.ExecuteScalar(countQuery, new
{
#PageNumber = page,
#Id = string.IsNullOrEmpty(filter) ? null : filter
});
*/
ViewData["PageSize"] = 30;
ViewData["Filter"] = filter;
}
if (userActivity != null)
{
return RedirectToAction(returnUrl);
}
return View(userActivity);
}
}
Really appreciate if there anyone who know something about this problem. Thanks

if (userActivity != null)
{
return RedirectToAction(returnUrl);
}
If the returnUrl points to the same action ("UserActivity/Index") it will create infinite redirect loop. If you want to redirect request to different action make sure you pass correct name.

You have a loop back situation. This is similar to endless while loop. To fix it change your code redirection implementation to redirect to an action method. Notice how I have changed the implementation below. This will fix the issue "localhost redirected you too many times". You can improve on it to support passing in parameters, etc suitable for your situation. Also take a look at RedirectToAction with support for additional parameters, if you want to pass parameters to the action method, this link will be useful.
public class UserActivityController : BaseController
{
//GET /UserActivity/Index
public ActionResult Index(int page = 1, string sort = "Id", string sortDir = "ASC", string filter = null)
{
// Your other implementation here. I have removed it for brevity.
if (userActivity != null)
{
return RedirectToAction("Index");
}
return View(userActivity);
}
public ActionResult Index()
{
return View();
}
}

I don't know what is the value of redirectUrl but I suppose it to be null. I also suppose that your userActivity is not null. So return RedirectToAction(returnUrl); gets called.
When you call RedirectToAction(null) you actually redirect to the same action and everything repeats again.
I also am wondering why would you need to return View(userActivity); when your userActivity is null. I suppose you have a logical error.

Related

BindingResult.getFieldValue() returning null in test context for a formatted value

In a spring mvc app, I submit id's and use a formatter to convert that id to an object. It works well in the container.
But in the unit test environment, I'm seeing a problem.
I mock the formatter to always return my test value, this is fine it gets injected into the ModelAttribute. But in the BindingResult, a call to result.getFieldValue("location") for example is returning null, but only in the MockMvc context.
This is the test case:
/**
* Tests the inventory update for existing inventory records.
* #throws Exception
*/
#Test
public void testUpdateExistingProductInventory() throws Exception{
logger.entry();
VariantInventory oldInventory = new VariantInventory();
oldInventory.setId(20l);
Product product = ProductBuilder.buildBasicExisting();
Location location = new Location();
location.setId(3l);
ProductVariant variant = new ProductVariant();
variant.setId(2l);
// check the formatter is working
Mockito.when(mockProductFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(product);
Product p = mockProductFormatter.parse("1", null);
Assert.assertEquals(p, product);
// check the formatter is working
Mockito.when(mockLocationFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(location);
Location l = mockLocationFormatter.parse("3", null);
Assert.assertEquals(l, location);
// check the formatter is working
Mockito.when(mockVariantFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(variant);
ProductVariant pv = mockVariantFormatter.parse("2", null);
Assert.assertEquals(pv, variant);
// check the formatter is working
Mockito.when(mockInventoryFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(oldInventory);
VariantInventory v = mockInventoryFormatter.parse("20", null);
Assert.assertEquals(v, oldInventory);
this.mockMvc.perform(MockMvcRequestBuilders.post("/ajax/products/update/inventory")
.param("product", "1")
.param("variant", "2")
.param("location", "3")
.param("status", "ACTIVE")
.param("quantityOnHand", "30.5")
.param("lowStockQuantity", "10")
.param("inventory", "20")
)
.andExpect(status().isOk());
Mockito.verify(mockInventoryService, Mockito.times(1)).updateExisting(Mockito.eq(oldInventory), Mockito.any(VariantInventory.class));
logger.exit();
}
This is the relative part of the controller:
#RequestMapping(value = "/ajax/products/update/inventory", method= RequestMethod.POST)
public #ResponseBody
AJAXResponse updateProductInventory(#ModelAttribute ProductInventoryFormWrapper formWrapper, BindingResult result,
ModelMap map) {
logger.entry();
logger.debug("Getting product data");
if (!result.hasErrors()) {
inventoryValidator.validate(formWrapper, result);
}
}
Then skipping a few items, this is the relevant validation that fails, where I am passing location as the field.
ValidationUtils.rejectIfEmptyOrWhitespace(errors, field, "required.field", new String[]{label});
The object fails to validate because of what must be a bug.
What I observe if I debug the controller is:
The object is in the FormWrapper, and the properties are there.
But in the BindingResult object, if I call 'getFieldValue('location')` which is what's being called in the spring validation code, it's returning null, and therefore the validator rejects the value.
So for some reason the binding result hasn't registered the formatted fields or something. Note that this only happens in the Unit Test, not in the container.
Does anyone know how to fix?
Quick Edit:
I've done some more debugging, and it's failing in this block of code from AbstractPropertyBindingResult. The value is okay right up until the conversionService is called to convert it. I haven't downloaded the source beyond that method, so I can't see exactly why it's failing, but somewhere in the convert method it's being turned from the proper value, to null. I presume because I'm using MockObjects, and maybe it's calling something that I haven't anticipated to return the value.
#Override
protected Object formatFieldValue(String field, Object value) {
String fixedField = fixedField(field);
// Try custom editor...
PropertyEditor customEditor = getCustomEditor(fixedField);
if (customEditor != null) {
customEditor.setValue(value);
String textValue = customEditor.getAsText();
// If the PropertyEditor returned null, there is no appropriate
// text representation for this value: only use it if non-null.
if (textValue != null) {
return textValue;
}
}
if (this.conversionService != null) {
// Try custom converter...
TypeDescriptor fieldDesc = getPropertyAccessor().getPropertyTypeDescriptor(fixedField);
TypeDescriptor strDesc = TypeDescriptor.valueOf(String.class);
if (fieldDesc != null && this.conversionService.canConvert(fieldDesc, strDesc)) {
return this.conversionService.convert(value, fieldDesc, strDesc);
}
}
return value;
}
Ok that was a tough one, so I didn't really expect anyone to answer. But here's the answer. I was right, the Mock was being called in the validation. So I had to add an additional mock method to the formatters (print):
// check the formatter is working
Mockito.when(mockInventoryFormatter.parse(((String)Mockito.anyObject()), ((Locale)Mockito.anyObject()))).thenReturn(oldInventory);
// this was added
Mockito.when(mockInventoryFormatter.print(Mockito.any(VariantInventory.class), Mockito.any(Locale.class))).thenReturn("20");

How should a C# Web API model binder provider work?

I have the following:
request url: 'endpoint/1,2,3?q=foo'
action to which the request is bound:
public object Bar([ModelBinder] List< T > ids, [FromUri] string q)
I want to map the "1,2,3" fragment to the "ids" parameter, so I created a ModelBinderProvider according to this link, which should call the proper model binder.
public class MyModelBinderProvider: ModelBinderProvider
{
public override IModelBinder GetBinder(HttpConfiguration configuration, Type modelType)
{
IModelBinder modelBinder = null;
if (modelType.IsGenericType && (modelType.GetGenericTypeDefinition() == typeof(List<>)))
{
modelBinder = new ListModelBinder();
}
return modelBinder;
}
}
I registered the provider in Global.asax like this:
GlobalConfiguration.Configuration.Services.Insert(typeof(ModelBinderProvider), 0, new MyModelBinderProvider());
The reason: I created this provider because I want, no matter what T is ('1,2,3' or 'one,two,three'), the bind to work.
The problem:
Let' say T is 'int'; everytime a request is sent, the 'modelType' paramater is always 'int' and not what I expect - 'List< int >', so the request is not properly handled.
The weird thing: Doing something like this works but T is specialized and therefor not what I want:
var simpleProvider = new SimpleModelBinderProvider(typeof(List<int>), new ListModelBinder());
GlobalConfiguration.Configuration.Services.Insert(typeof(ModelBinderProvider), 0, simpleProvider);
I cannot see what I'm doing wrong, why is the 'modelType' parameter not the expected value?
It is a very old question but I had an similar issue here with a legacy code.
Commas are reserved and it should be avoided although they work in some cases but if you really want to use them...
I think that is more a route issue than a model binder once the "1,2,3" is path part of the url. Assuming this I wrote a small RouteHandler that does the trick (please forgive the very simple "word to integer" translator).
The CsvRouteHandler gets the id array from URL and put it on RouteData as an array of integers. If the original array has words such as one, two or three it translates each value to int.
MvcRouteHandler
protected override IHttpHandler GetHttpHandler(System.Web.Routing.RequestContext requestContext)
{
var idArrayParameter = requestContext.RouteData.Values["idArray"] != null ? requestContext.RouteData.Values["idArray"].ToString() : null;
if (string.IsNullOrEmpty(idArrayParameter))
{
return base.GetHttpHandler(requestContext);
}
requestContext.RouteData.Values.Remove("idArray"); // remove the old array from routedata
// Note: it is horrible and bugged but and you probably have your own translation method :)
string[] idArray = idArrayParameter.Split(',');
int[] ids = new int[idArray.Length];
for(int i = 0; i < idArray.Length; i++)
{
if (!int.TryParse(idArray[i], out ids[i]))
{
switch (idArray[i])
{
case "one":
ids[i] = 1;
break;
case "two":
ids[i] = 2;
break;
case "three":
ids[i] = 3;
break;
}
}
}
requestContext.RouteData.Values.Add("Id", ids);
return base.GetHttpHandler(requestContext);
}
}
Route configuration:
routes.Add(
name: "Id Array Route",
item: new Route(
url: "endpoint/{idArray}",
defaults: new RouteValueDictionary(new { controller = "Test", action = "Index" }),
routeHandler: new CsvRouteHandler())
);

ASP.NET MVC 4 Custom Action filters with dynamic data

So I am building a web application that I want to sell once Im done with it. It allows the user to enter data such as their website name, meta keywords, their contact email, phone, address etc in the admin panel. I wrote a Action Filter in order to include these values in every request that I put the filter on so I didnt have to query for them every time because these values are included in the common footer throughout the site. However, I learned that if I update the database with new or different information for these values, it does not update on the web pages which im guessing is because Action Filters are configured at application start up. In the Action Filter I am using a repository pattern to query for these values. I have included the code for the action filter below. How can I have the convenience of the Action Filter but be able to update it dynamically when the data changes in the database? Thanks!
public class ViewBagActionFilter : ActionFilterAttribute,IActionFilter
{
Repositories.SettingsRepository _repo = new Repositories.SettingsRepository();
void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)
{
base.OnActionExecuted(filterContext);
}
void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)
{
string siteName = _repo.GetSiteName();
string siteDesc = _repo.GetSiteDescription();
string siteKeywords = _repo.GetSiteKeywords();
string googleAnalytics = _repo.GetGoogleAnalytics();
string streetAddress = _repo.GetStreetAddress();
string zipCode = _repo.GetZipCode();
string city = _repo.GetCity();
string state = _repo.GetState();
string aboutUs = _repo.GetAboutUs();
string phone = _repo.GetPhoneNumber();
string contactEmail = _repo.GetContactEmail();
if (!string.IsNullOrWhiteSpace(siteName) && siteName.Length > 0)
{
string[] splitSiteName = new string[siteName.Length/2];
splitSiteName = siteName.Split(' ');
if (splitSiteName.Length > 1)
{
filterContext.Controller.ViewBag.SiteName1 = splitSiteName[0];
filterContext.Controller.ViewBag.SiteName2 = splitSiteName[1];
}
else
{
filterContext.Controller.ViewBag.SiteName1 = splitSiteName[0];
filterContext.Controller.ViewBag.SiteName2 = "";
}
}
//Set default values for common viewbag items that are on every page using ternary syntax
filterContext.Controller.ViewBag.SiteDescription = (!string.IsNullOrWhiteSpace(siteDesc) && siteDesc.Length > 0) ? siteDesc : "";
filterContext.Controller.ViewBag.SiteKeywords = (!string.IsNullOrWhiteSpace(siteKeywords) && siteKeywords.Length > 0) ? siteKeywords : "";
filterContext.Controller.ViewBag.GoogleAnalytics = (!string.IsNullOrWhiteSpace(googleAnalytics) && googleAnalytics.Length > 0) ? googleAnalytics : "";
filterContext.Controller.ViewBag.StreetAddress = (!string.IsNullOrWhiteSpace(streetAddress) && streetAddress.Length > 0) ? streetAddress : "";
filterContext.Controller.ViewBag.ZipCode = (!string.IsNullOrWhiteSpace(zipCode) && zipCode.Length > 0) ? zipCode : "";
filterContext.Controller.ViewBag.City = (!string.IsNullOrWhiteSpace(city) && city.Length > 0) ? city : "";
filterContext.Controller.ViewBag.State = (!string.IsNullOrWhiteSpace(state) && state.Length > 0) ? state : "";
filterContext.Controller.ViewBag.AboutUs = (!string.IsNullOrWhiteSpace(aboutUs) && aboutUs.Length > 0) ? aboutUs : "";
filterContext.Controller.ViewBag.PhoneNumber = (!string.IsNullOrWhiteSpace(phone) && phone.Length > 0) ? phone : "";
filterContext.Controller.ViewBag.ContactEmail = (!string.IsNullOrWhiteSpace(contactEmail) && contactEmail.Length > 0) ? contactEmail : "";
base.OnActionExecuting(filterContext);
}
}
I will try to explain how action filters works.
So if you extend Action filter you can override 4 base methods :
OnActionExecuting – This method is called before a controller action is executed.
OnActionExecuted – This method is called after a controller action is executed.
OnResultExecuting – This method is called before a controller action result is executed.
OnResultExecuted – This method is called after a controller action result is executed.
So thats mean that you method will be called each time before Controller will run action.
Now about optimization. You have
string siteName = _repo.GetSiteName();
string siteDesc = _repo.GetSiteDescription();
string siteKeywords = _repo.GetSiteKeywords();
string googleAnalytics = _repo.GetGoogleAnalytics();
string streetAddress = _repo.GetStreetAddress();
string zipCode = _repo.GetZipCode();
string city = _repo.GetCity();
string state = _repo.GetState();
string aboutUs = _repo.GetAboutUs();
string phone = _repo.GetPhoneNumber();
string contactEmail = _repo.GetContactEmail();
I would suggest you to create one class
public class Site{
public string SiteName{get;set;}
public string City{get;set;}
//And so on just to add all properties
}
then in repository add one more method
_repo.GetSite(); //Which will return object Site
Then
filterContext.Controller.ViewBag.CurrentSite = _repo.GetSite();
And now probably the most important for you. Why it doesnot work as you want and its a bit simple. Attribute class is initialized only once on Application start and after that it doesnot reloads, and your implementation is a bit strange since
Repositories.SettingsRepository _repo = new Repositories.SettingsRepository();
I suppose here you are loading settings. So after you load you did not reload it anymore... thats mean you will get same result each time you reload page, but if you restart iis for instance you will refresh data.
Possible solution
Move initialization of _repo to OnActionExecuting then it will reload data each time, or rewrite repository as i suggested and
filterContext.Controller.ViewBag.CurrentSite = _repo.GetSite();
Should always load new data from db.
Hope it helps :)

How to get a diff of pending changes to a model in ASP.NET MVC 2

I am working on an ASP.Net MVC app and I want to show a confirmation page after the user edits some data. What I would like to show is a list of the pending changes that the user made to the model.
For example,
Are you sure you want to make the following changes:
FieldName:
Previous Value: XXX
New Value: YYY
I know I can read my stored value from the database and compare it with the POSTed object but I want this to work generally. What would be some good ways to approach this?
To clarify, I am looking for a general way to get a "diff" of the pending changes. I already know how to get the previous and pending changes. Kind of like how TryUpdateModel() can attempt to update any Model with posted values. I'd like a magical GetPendingModelChanges() method that can return a list of something like new PendingChange { Original = "XXX", NewValue = "YYY"} objects.
You might be doing this already but I wouldn't send my model to the view, create a viewmodel. In this case I would map the model data to the viewmodel twice, my viewmodel might contain OrderInput and OrderInputOrig. Then stick OrderInputOrig in hidden fields. On post back you can compare the values and then redirect, if something changed, to a display view with the original and the changes for confirmation.
Maybe something like this:
[HttpPost]
public ActionResult Edit(CustomerInput cutomerInput)
{
var changes = PublicInstancePropertiesEqual(cutomerInput.OriginalCustomer, cutomerInput.Customer);
if (changes != null)
{
cutomerInput.WhatChangeds = changes;
return View("ConfirmChanges", cutomerInput);
}
return View();
}
public ActionResult ConfirmChanges(CustomerInput customerInput)
{
return View(customerInput);
}
from: Comparing object properties in c#
public static Dictionary<string, WhatChanged> PublicInstancePropertiesEqual<T>(T self, T to, params string[] ignore) where T : class
{
Dictionary<string, WhatChanged> changes = null;
if (self != null && to != null)
{
var type = typeof(T);
var ignoreList = new List<string>(ignore);
foreach (System.Reflection.PropertyInfo pi in type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance))
{
if (!ignoreList.Contains(pi.Name))
{
var selfValue = type.GetProperty(pi.Name).GetValue(self, null);
var toValue = type.GetProperty(pi.Name).GetValue(to, null);
if (selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue)))
{
if (changes == null)
changes = new Dictionary<string, WhatChanged>();
changes.Add(pi.Name, new WhatChanged
{
OldValue = selfValue,
NewValue=toValue
});
}
}
}
return changes;
}
return null;
}
Coming in very late here, but I created a library to do this on MVC models and providing "readable" diffs for humans using MVC ModelMetadata:
https://github.com/paultyng/ObjectDiff
It gives me output when I save a Model similar to:
Status: 'Live', was 'Inactive'
Phone: '123-456-7898', was '555-555-5555'
Etc.
use the TempData Dictionary.
TempData["previousValue"];
TempData["newValue"];

Webtest with session-id in url

We have an ASP.Net site that redirects you to a url that shows a session-id. like this:
http://localhost/(S(f3rjcw45q4cqarboeme53lbx))/main.aspx
This id is unique with every request.
Is it possible to test this site using a standard visual studio 2008/2010 webtest? How can I provide the test this data?
I have to call a couple of different pages using that same id.
Yes, it is relatively easy to do this. You will need to create a coded webtest however.
In my example we have a login post that will return the url including the session string.
Just after the we yield the login post request (request3) to the enumerator I call the following.
WebTestRequest request3 = new WebTestRequest((this.Context["WebServer1"].ToString() + "/ICS/Login/English/Login.aspx"));
//more request setup code removed for clarity
yield return request3;
string responseUrl = Context.LastResponse.ResponseUri.AbsoluteUri;
string cookieUrl = GetUrlCookie(responseUrl, this.Context["WebServer1"].ToString(),"/main.aspx");
request3 = null;
Where GetUrlCookie is something like this:
public static string GetUrlCookie(string fullUrl, string webServerUrl, string afterUrlPArt)
{
string result = fullUrl.Substring(webServerUrl.Length);
result = result.Substring(0, result.Length - afterUrlPArt.Length);
return result;
}
Once you have the session cookie string, you can substitute it really easy in any subsequent urls for request/post
e.g.
WebTestRequest request4 = new WebTestRequest((this.Context["WebServer1"].ToString() + cookieUrl + "/mySecureForm.aspx"));
I apologise for my code being so rough, but it was deprecated in my project and is pulled from the first version of the codebase - and for saying it was easy :)
For any load testing, depending on your application, you may have to come up with a stored procedure to call to provide distinct login information each time the test is run.
Note, because the response url cannot be determined ahead of time, for the login post you will have to temporarily turn off the urlValidationEventHandler. To do this I store the validationruleeventhandler in a local variable:
ValidateResponseUrl validationRule1 = new ValidateResponseUrl();
urlValidationRuleEventHandler = new EventHandler<ValidationEventArgs>(validationRule1.Validate);
So can then turn it on and off as I require:
this.ValidateResponse -= urlValidationRuleEventHandler ;
this.ValidateResponse += urlValidationRuleEventHandler ;
The alternative is to code your own such as this (reflectored from the Visual Studio code and changed to be case insensitive.
class QueryLessCaseInsensitiveValidateResponseUrl : ValidateResponseUrl
{
public override void Validate(object sender, ValidationEventArgs e)
{
Uri uri;
string uriString = string.IsNullOrEmpty(e.Request.ExpectedResponseUrl) ? e.Request.Url : e.Request.ExpectedResponseUrl;
if (!Uri.TryCreate(e.Request.Url, UriKind.Absolute, out uri))
{
e.Message = "The request URL could not be parsed";
e.IsValid = false;
}
else
{
Uri uri2;
string leftPart = uri.GetLeftPart(UriPartial.Path);
if (!Uri.TryCreate(uriString, UriKind.Absolute, out uri2))
{
e.Message = "The request URL could not be parsed";
e.IsValid = false;
}
else
{
uriString = uri2.GetLeftPart(UriPartial.Path);
////this removes the query string
//uriString.Substring(0, uriString.Length - uri2.Query.Length);
Uri uritemp = new Uri(uriString);
if (uritemp.Query.Length > 0)
{
string fred = "There is a problem";
}
//changed to ignore case
if (string.Equals(leftPart, uriString, StringComparison.OrdinalIgnoreCase))
{
e.IsValid = true;
}
else
{
e.Message = string.Format("The value of the ExpectedResponseUrl property '{0}' does not equal the actual response URL '{1}'. QueryString parameters were ignored.", new object[] { uriString, leftPart });
e.IsValid = false;
}
}
}
}
}

Resources