Converting List in Comma Separated List with linq? - asp.net

I am having a info class with following field like id,name,address and i have created list of that info like List.
I want to have all the values of list into comma seperated strings using linq. Is there any way for this.

simple way... may not be the fastest so it depends on how many records you are processing
var myObjects = new[] {
new {
id=1,
name="Matt",
address="1234 no chance ln\r\nnowhere, OH 12345"
},
new {
id=1,
name="Jim",
address="4321 no chance ln\r\nnowhere, OH 12345"
}
};
var myList = (from o in myObjects
select string.Format("{0},\"{1}\",\"{2}\"",
o.id,
o.name,
(o.address ?? string.Empty).Replace("\r\n", ";")
)).ToList();

Have a look at this example by Mike Hadlow. It needs some improvement (escaping commas, new line support etc) but gives you the basic idea.

Taken from the LinQExtensions.cs found at Batch Updates and Deletes with LINQ to SQL
/// <summary>
/// Creates a *.csv file from an IQueryable query, dumping out the 'simple' properties/fields.
/// </summary>
/// <param name="query">Represents a SELECT query to execute.</param>
/// <param name="fileName">The name of the file to create.</param>
/// <remarks>
/// <para>If the file specified by <paramref name="fileName"/> exists, it will be deleted.</para>
/// <para>If the <paramref name="query"/> contains any properties that are entity sets (i.e. rows from a FK relationship) the values will not be dumped to the file.</para>
/// <para>This method is useful for debugging purposes or when used in other utilities such as LINQPad.</para>
/// </remarks>
public static void DumpCSV(this IQueryable query, string fileName)
{
query.DumpCSV(fileName, true);
}
/// <summary>
/// Creates a *.csv file from an IQueryable query, dumping out the 'simple' properties/fields.
/// </summary>
/// <param name="query">Represents a SELECT query to execute.</param>
/// <param name="fileName">The name of the file to create.</param>
/// <param name="deleteFile">Whether or not to delete the file specified by <paramref name="fileName"/> if it exists.</param>
/// <remarks>
/// <para>If the <paramref name="query"/> contains any properties that are entity sets (i.e. rows from a FK relationship) the values will not be dumped to the file.</para>
/// <para>This method is useful for debugging purposes or when used in other utilities such as LINQPad.</para>
/// </remarks>
public static void DumpCSV(this IQueryable query, string fileName, bool deleteFile)
{
if (File.Exists(fileName) && deleteFile)
{
File.Delete(fileName);
}
using (var output = new FileStream(fileName, FileMode.CreateNew))
{
using (var writer = new StreamWriter(output))
{
var firstRow = true;
PropertyInfo[] properties = null;
FieldInfo[] fields = null;
Type type = null;
bool typeIsAnonymous = false;
foreach (var r in query)
{
if (type == null)
{
type = r.GetType();
typeIsAnonymous = type.IsAnonymous();
properties = type.GetProperties();
fields = type.GetFields();
}
var firstCol = true;
if (typeIsAnonymous)
{
if (firstRow)
{
foreach (var p in properties)
{
if (!firstCol) writer.Write(",");
else { firstCol = false; }
writer.Write(p.Name);
}
writer.WriteLine();
}
firstRow = false;
firstCol = true;
foreach (var p in properties)
{
if (!firstCol) writer.Write(",");
else { firstCol = false; }
DumpValue(p.GetValue(r, null), writer);
}
}
else
{
if (firstRow)
{
foreach (var p in fields)
{
if (!firstCol) writer.Write(",");
else { firstCol = false; }
writer.Write(p.Name);
}
writer.WriteLine();
}
firstRow = false;
firstCol = true;
foreach (var p in fields)
{
if (!firstCol) writer.Write(",");
else { firstCol = false; }
DumpValue(p.GetValue(r), writer);
}
}
writer.WriteLine();
}
}
}
}
private static void DumpValue(object v, StreamWriter writer)
{
if (v != null)
{
switch (Type.GetTypeCode(v.GetType()))
{
// csv encode the value
case TypeCode.String:
string value = (string)v;
if (value.Contains(",") || value.Contains('"') || value.Contains("\n"))
{
value = value.Replace("\"", "\"\"");
if (value.Length > 31735)
{
value = value.Substring(0, 31732) + "...";
}
writer.Write("\"" + value + "\"");
}
else
{
writer.Write(value);
}
break;
default: writer.Write(v); break;
}
}
}
private static bool IsAnonymous(this Type type)
{
if (type == null)
throw new ArgumentNullException("type");
// HACK: The only way to detect anonymous types right now.
return Attribute.IsDefined(type, typeof(CompilerGeneratedAttribute), false)
&& type.IsGenericType && type.Name.Contains("AnonymousType")
&& (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
&& (type.Attributes & TypeAttributes.NotPublic) == TypeAttributes.NotPublic;
}

Related

Xunit CSV streamReader.ReadToEnd returns System.ArgumentOutOfRangeException

I would like to evaluate a CSV data series with Xunit.
For this I need to read in a string consisting of int, bool, double and others.
With the following code, the transfer basically works for one row.
But since I want to test for predecessor values, I need a whole CSV file for evaluation.
My [Theory] works with InlineData without errors.
But when I read in a CSV file, the CSVDataHandler gives a System.ArgumentOutOfRangeException!
I can't find a solution for the error and ask for support.
Thanks a lot!
[Theory, CSVDataHandler(false, "C:\\MyTestData.txt", Skip = "")]
public void TestData(int[] newLine, int[] GetInt, bool[] GetBool)
{
for (int i = 0; i < newLine.Length; i++)
{
output.WriteLine("newLine {0}", newLine[i]);
output.WriteLine("GetInt {0}", GetInt[i]);
output.WriteLine("GetBool {0}", GetBool[i]);
}
}
[DataDiscoverer("Xunit.Sdk.DataDiscoverer", "xunit.core")]
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public abstract class DataArribute : Attribute
{
public abstract IEnumerable<object> GetData(MethodInfo methodInfo);
public virtual string? Skip { get; set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : DataAttribute
{
public CSVDataHandler(bool hasHeaders, string pathCSV)
{
this.hasHeaders = hasHeaders;
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
var methodParameters = methodInfo.GetParameters();
var paramterTypes = methodParameters.Select(p => p.ParameterType).ToArray();
using (var streamReader = new StreamReader(pathCSV))
{
if (hasHeaders) { streamReader.ReadLine(); }
string csvLine = string.Empty;
// ReadLine ++
//while ((csvLine = streamReader.ReadLine()) != null)
//{
// var csvRow = csvLine.Split(',');
// yield return ConvertCsv((object[])csvRow, paramterTypes);
//}
// ReadToEnd ??
while ((csvLine = streamReader.ReadToEnd()) != null)
{
if (Environment.NewLine != null)
{
var csvRow = csvLine.Split(',');
yield return ConvertCsv((object[])csvRow, paramterTypes); // System.ArgumentOutOfRangeException
}
}
}
}
private static object[] ConvertCsv(IReadOnlyList<object> cswRow, IReadOnlyList<Type> parameterTypes)
{
var convertedObject = new object[parameterTypes.Count];
for (int i = 0; i < parameterTypes.Count; i++)
{
convertedObject[i] = (parameterTypes[i] == typeof(int)) ? Convert.ToInt32(cswRow[i]) : cswRow[i]; // System.ArgumentOutOfRangeException
convertedObject[i] = (parameterTypes[i] == typeof(double)) ? Convert.ToDouble(cswRow[i]) : cswRow[i];
convertedObject[i] = (parameterTypes[i] == typeof(bool)) ? Convert.ToBoolean(cswRow[i]) : cswRow[i];
}
return convertedObject;
}
}
MyTestData.txt
1,2,true,
2,3,false,
3,10,true,
The first call to streamReader.ReadToEnd() will return the entire contents of the file in a string, not just one line. When you call csvLine.Split(',') you will get an array of 12 elements.
The second call to streamReader.ReadToEnd() will not return null as your while statement appears to expect, but an empty string. See the docu at
https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.readtoend?view=net-7.0
If the current position is at the end of the stream, returns an empty
string ("").
With the empty string, the call to call csvLine.Split(',') will return an array of length 0, which causes your exception when its first element (index 0) is accessed.
All of this could have been easily discovered by simply starting the test in a debugger.
It looks like you have some other issues here as well.
I don't understand what your if (Environment.NewLine != null) is intended to do, the NewLine property will never be null but should have one of the values "\r\n" or "\n" so the if will always be taken.
The parameters of your test method are arrays int[] and bool[], but you are checking against the types int, double and bool in your ConvertCsv method, so the alternative cswRow[i] will always be returned. You'll wind up passing strings to your method expecting int[] and bool[] and will at latest get an error there.
This method reads a data series from several rows and columns and returns it as an array for testing purposes.
The conversion of the columns can be adjusted according to existing pattern.
Thanks to Christopher!
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)]
public class CSVDataHandler : Xunit.Sdk.DataAttribute
{
public CSVDataHandler(string pathCSV)
{
this.pathCSV = pathCSV;
}
public override IEnumerable<object[]> GetData(MethodInfo methodInfo)
{
List<int> newLine = new();
List<int> GetInt = new();
List<bool> GetBool = new();
var reader = new StreamReader(pathCSV);
string readData = string.Empty;
while ((readData = reader.ReadLine()) != null)
{
string[] split = readData.Split(new char[] { ',' });
newLine.Add(int.Parse(split[0]));
GetInt.Add(int.Parse(split[1]));
GetBool.Add(bool.Parse(split[2]));
// Add more objects ...
}
yield return new object[] { newLine.ToArray(), GetInt.ToArray(), GetBool.ToArray() };
}
}

Swagger/Redoc <remarks> not showing

I am trying to get the XML comments working properly in the docs page, but am having trouble getting the to show. descriptions show just fine, but the remarks are missing completely.
My Swagger config includes c.IncludeXmlComments($#"{AppDomain.CurrentDomain.BaseDirectory}\App_Data\XmlDocument.XML"); and I've confirmed the xml file contains the proper remarks.
All the properties are setup similar to this:
namespace My.Namespace
{
public class SomeRequestObject
{
/// <summary>
/// Some Property
/// </summary>
/// <remarks>
/// Details about this prop
/// More details about this prop
/// </remarks>
public string SomeProperty { get; set; }
}
}
I can see the remarks on the method calls themselves, but not on the object properties.
Any ideas on how to get the remarks to show in the UI?
Ok, so I couldn't find a built-in way to do this, but what I ended up doing was creating a custom schema filter and then "manually" added the remarks to the description.
SwaggerConfig.cs:
public class SwaggerConfig
{
public static void Register()
{
GlobalConfiguration.Configuration
.EnableSwagger(c =>
{
// ...Other config options
c.SchemaFilter<CustomSwaggerSchemaFilter>();
});
}
}
Then in the CustomSwaggerFilter.cs file I did:
public class CustomSwaggerSchemaFilter : ISchemaFilter
{
public void Apply(Schema outputSchema, SchemaRegistry schemaRegistry, Type inputType)
{
//Get properties and filter out dupes/empties
var props = inputType.GetProperties().ToList();
var baseProps = inputType.BaseType?.GetProperties().ToList();
if (baseProps != null && baseProps.Any(bp => props.Any(p => p.Name == bp.Name)))
{
baseProps.ForEach(bp =>
{
var indexToRemove = props.FindIndex(x => x.Name == bp.Name);
props.RemoveAt(indexToRemove);
props.Add(bp);
});
}
foreach (var prop in props)
{
//Get the remarks in the documentation
var propType = prop.ReflectedType;
var remarks = propType.GetDocumentationComment("remarks", 'P', prop.Name);
var outputProp = outputSchema.properties.FirstOrDefault(x => string.Equals(x.Key, prop.Name, StringComparison.OrdinalIgnoreCase));
if (outputProp.Value != null && !string.IsNullOrEmpty(remarks))
{
//Format remarks to display better
var formattedRemarks = string.Empty;
var remarkList = remarks.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var remark in remarkList)
{
formattedRemarks += $" \r\n_{remark.Trim()}_";
}
//Append to the description
outputProp.Value.description += formattedRemarks;
}
}
}
}
Which results in something like this:

Asp.Net Repeater loses data on postback

My problem is a bit more complicated than the title says:
I made a user control (I called it editor) for editing Data base data into another user control I also made(I called it GridView).
The editor is use for each row (a row is also a usercontrol and the editor is only inside row even for insert) inside my gridview and work perfectly but not when I try to use it to insert.
The only difference between insert and edit is this Field:
#region Field
/// <summary>
///
/// </summary>
//public Field Field { get { return DataItem as Field; } }
private Field _field;
[Bindable(true)]
public Field Field
{
get
{
if (IsInsert && _field == null)
{
_field = SubscriptionController.CreateField();
}
return _field;
}
set { _field = value; }
}
#endregion
Inside this Field I've the collection I bind to the repeater
the SubscriptionController.CreateField(); method just create an instance of Field class and all collection inside here is the code:
public Field CreateField()
{
Field field = new Field();
field.Type = GetFieldTypes().First();
field.Label = new LocalizedStringCollection();
field.Values = new FieldValueCollection();
field.Selections = new FieldSelectionCollection();
foreach (Models.TrainingGroup trainingGroup in GetTrainingGroup())
{
foreach (Models.Division division in GetDivisions())
{
foreach (Models.ProfilStatusGroup profilStatusGroup in GetProfilStatusGroup())
{
field.Selections.Add(new Models.FieldSelection() { Selected = false, DivisionId = division.Id, ProfilStatusGroupId = profilStatusGroup.Id, TrainingGroupId = trainingGroup.Id });
}
}
}
}
the collection I bind is stored in viewstate :
#region FieldValues
/// <summary>
/// Get/Set FieldValues from Viewstate
/// </summary>
public FieldValueCollection FieldValues
{
get
{
if (ViewState["FieldValues"] == null)
{
if (Field != null && Field.Values != null)
ViewState.Add("FieldValues", Field.Values);
else
ViewState.Add("FieldValues", new FieldValueCollection());
}
if (ViewState["FieldValues"] != null)
{
return (FieldValueCollection)ViewState["FieldValues"];
}
return null;
}
set
{
if (ViewState["FieldValues"] == null)
{
ViewState.Add("FieldValues", value);
}
else
{
ViewState["FieldValues"] = value;
}
}
}
#endregion
but when I get on postback all textboxes inside my repeater are empty.

What Good way to keep some different data in Cookies in asp.net?

I want to keep some different data in one cookie file and write this class, and want to know - is this good? For example - user JS enable.When user open his first page on my site, i write to session his GMT time and write with this manager JS state. (GMT time is ajax request with js). And i want to keep some data in this cookie (up to 10 values). Have any advices or tips?
/// <summary>
/// CookiesSettings
/// </summary>
internal enum CookieSetting
{
IsJsEnable = 1,
}
internal class CookieSettingValue
{
public CookieSetting Type { get; set; }
public string Value { get; set; }
}
/// <summary>
/// Cookies to long time of expire
/// </summary>
internal class CookieManager
{
//User Public Settings
private const string CookieValueName = "UPSettings";
private string[] DelimeterValue = new string[1] { "#" };
//cookie daat
private List<CookieSettingValue> _data;
public CookieManager()
{
_data = LoadFromCookies();
}
#region Save and load
/// <summary>
/// Load from cookie string value
/// </summary>
private List<CookieSettingValue> LoadFromCookies()
{
if (!CookieHelper.RequestCookies.Contains(CookieValueName))
return new List<CookieSettingValue>();
_data = new List<CookieSettingValue>();
string data = CookieHelper.RequestCookies[CookieValueName].ToString();
string[] dels = data.Split(DelimeterValue, StringSplitOptions.RemoveEmptyEntries);
foreach (string delValue in dels)
{
int eqIndex = delValue.IndexOf("=");
if (eqIndex == -1)
continue;
int cookieType = ValidationHelper.GetInteger(delValue.Substring(0, eqIndex), 0);
if (!Enum.IsDefined(typeof(CookieSetting), cookieType))
continue;
CookieSettingValue value = new CookieSettingValue();
value.Type = (CookieSetting)cookieType;
value.Value = delValue.Substring(eqIndex + 1, delValue.Length - eqIndex-1);
_data.Add(value);
}
return _data;
}
public void Save()
{
CookieHelper.SetValue(CookieValueName, ToCookie(), DateTime.UtcNow.AddMonths(6));
}
#endregion
#region Get value
public bool Bool(CookieSetting type, bool defaultValue)
{
CookieSettingValue inList = _data.SingleOrDefault(x => x.Type == type);
if (inList == null)
return defaultValue;
return ValidationHelper.GetBoolean(inList.Value, defaultValue);
}
#endregion
#region Set value
public void SetValue(CookieSetting type, int value)
{
CookieSettingValue inList = _data.SingleOrDefault(x => x.Type == type);
if (inList == null)
{
inList = new CookieSettingValue();
inList.Type = type;
inList.Value = value.ToString();
_data.Add(inList);
}
else
{
inList.Value = value.ToString();
}
}
public void SetValue(CookieSetting type, bool value)
{
CookieSettingValue inList = _data.SingleOrDefault(x => x.Type == type);
if (inList == null)
{
inList = new CookieSettingValue();
inList.Type = type;
inList.Value = value.ToString();
_data.Add(inList);
}
else
{
inList.Value = value.ToString();
}
}
#endregion
#region Private methods
private string ToCookie()
{
StringBuilder sb = new StringBuilder();
for (int i = 0; i < _data.Count; i++)
{
sb.Append((int)_data[i].Type);
sb.Append("=");
sb.Append(_data[i].Value);
sb.Append(DelimeterValue[0]);
}
return sb.ToString();
}
/// <summary>
/// Cookie length in bytes. Max - 4 bytes
/// </summary>
/// <returns></returns>
private int GetLength()
{
return System.Text.Encoding.UTF8.GetByteCount(ToCookie());
}
#endregion
}
P.S. i want to keep many data in one cookies file to compress data and decrease cookies count.
Don't put data into cookies. All cookie data is uploaded from the client on every request to your web site. Even users with good broadband connections often have very limited upload bandwidth, and so storing significant data in cookies can be very bad for perceived performance.
Instead, simply store a value in the cookie that you can use as a lookup to a database table when needed.
Don't put data into cookie. What Joel say is stands and I like to say one more think. Browser some time behave strange if you have a large amount data on your cookie, and you get problems that you do not even imaging where they come from. And this is from my experience.
behave strange:They sow blank white pages, or they can not load the page and you see the cursor wait and wait, or lose the cookie, or you lose data from your cookie and you can not login for example, and other thinks like that.

How to decode viewstate

I need to see the contents of the viewstate of an asp.net page. I looked for a viewstate decoder, found Fridz Onion's ViewState Decoder but it asks for the url of a page to get its viewstate. Since my viewstate is formed after a postback and comes as a result of an operation in an update panel, I cannot provide a url. I need to copy & paste the viewstate string and see what's inside. Is there a tool or a website exist that can help viewing the contents of viewstate?
Here's an online ViewState decoder:
http://ignatu.co.uk/ViewStateDecoder.aspx
Edit: Unfortunatey, the above link is dead - here's another ViewState decoder (from the comments):
http://viewstatedecoder.azurewebsites.net/
Use Fiddler and grab the view state in the response and paste it into the bottom left text box then decode.
Here is the source code for a ViewState visualizer from Scott Mitchell's article on ViewState (25 pages)
using System;
using System.Collections;
using System.Text;
using System.IO;
using System.Web.UI;
namespace ViewStateArticle.ExtendedPageClasses
{
/// <summary>
/// Parses the view state, constructing a viaully-accessible object graph.
/// </summary>
public class ViewStateParser
{
// private member variables
private TextWriter tw;
private string indentString = " ";
#region Constructor
/// <summary>
/// Creates a new ViewStateParser instance, specifying the TextWriter to emit the output to.
/// </summary>
public ViewStateParser(TextWriter writer)
{
tw = writer;
}
#endregion
#region Methods
#region ParseViewStateGraph Methods
/// <summary>
/// Emits a readable version of the view state to the TextWriter passed into the object's constructor.
/// </summary>
/// <param name="viewState">The view state object to start parsing at.</param>
public virtual void ParseViewStateGraph(object viewState)
{
ParseViewStateGraph(viewState, 0, string.Empty);
}
/// <summary>
/// Emits a readable version of the view state to the TextWriter passed into the object's constructor.
/// </summary>
/// <param name="viewStateAsString">A base-64 encoded representation of the view state to parse.</param>
public virtual void ParseViewStateGraph(string viewStateAsString)
{
// First, deserialize the string into a Triplet
LosFormatter los = new LosFormatter();
object viewState = los.Deserialize(viewStateAsString);
ParseViewStateGraph(viewState, 0, string.Empty);
}
/// <summary>
/// Recursively parses the view state.
/// </summary>
/// <param name="node">The current view state node.</param>
/// <param name="depth">The "depth" of the view state tree.</param>
/// <param name="label">A label to display in the emitted output next to the current node.</param>
protected virtual void ParseViewStateGraph(object node, int depth, string label)
{
tw.Write(System.Environment.NewLine);
if (node == null)
{
tw.Write(String.Concat(Indent(depth), label, "NODE IS NULL"));
}
else if (node is Triplet)
{
tw.Write(String.Concat(Indent(depth), label, "TRIPLET"));
ParseViewStateGraph(((Triplet) node).First, depth+1, "First: ");
ParseViewStateGraph(((Triplet) node).Second, depth+1, "Second: ");
ParseViewStateGraph(((Triplet) node).Third, depth+1, "Third: ");
}
else if (node is Pair)
{
tw.Write(String.Concat(Indent(depth), label, "PAIR"));
ParseViewStateGraph(((Pair) node).First, depth+1, "First: ");
ParseViewStateGraph(((Pair) node).Second, depth+1, "Second: ");
}
else if (node is ArrayList)
{
tw.Write(String.Concat(Indent(depth), label, "ARRAYLIST"));
// display array values
for (int i = 0; i < ((ArrayList) node).Count; i++)
ParseViewStateGraph(((ArrayList) node)[i], depth+1, String.Format("({0}) ", i));
}
else if (node.GetType().IsArray)
{
tw.Write(String.Concat(Indent(depth), label, "ARRAY "));
tw.Write(String.Concat("(", node.GetType().ToString(), ")"));
IEnumerator e = ((Array) node).GetEnumerator();
int count = 0;
while (e.MoveNext())
ParseViewStateGraph(e.Current, depth+1, String.Format("({0}) ", count++));
}
else if (node.GetType().IsPrimitive || node is string)
{
tw.Write(String.Concat(Indent(depth), label));
tw.Write(node.ToString() + " (" + node.GetType().ToString() + ")");
}
else
{
tw.Write(String.Concat(Indent(depth), label, "OTHER - "));
tw.Write(node.GetType().ToString());
}
}
#endregion
/// <summary>
/// Returns a string containing the <see cref="IndentString"/> property value a specified number of times.
/// </summary>
/// <param name="depth">The number of times to repeat the <see cref="IndentString"/> property.</param>
/// <returns>A string containing the <see cref="IndentString"/> property value a specified number of times.</returns>
protected virtual string Indent(int depth)
{
StringBuilder sb = new StringBuilder(IndentString.Length * depth);
for (int i = 0; i < depth; i++)
sb.Append(IndentString);
return sb.ToString();
}
#endregion
#region Properties
/// <summary>
/// Specifies the indentation to use for each level when displaying the object graph.
/// </summary>
/// <value>A string value; the default is three blank spaces.</value>
public string IndentString
{
get
{
return indentString;
}
set
{
indentString = value;
}
}
#endregion
}
}
And here's a simple page to read the viewstate from a textbox and graph it using the above code
private void btnParse_Click(object sender, System.EventArgs e)
{
// parse the viewState
StringWriter writer = new StringWriter();
ViewStateParser p = new ViewStateParser(writer);
p.ParseViewStateGraph(txtViewState.Text);
ltlViewState.Text = writer.ToString();
}
As another person just mentioned, it's a base64 encoded string. In the past, I've used this website to decode it:
http://www.motobit.com/util/base64-decoder-encoder.asp
JavaScript-ViewState-Parser:
http://mutantzombie.github.com/JavaScript-ViewState-Parser/
https://github.com/mutantzombie/JavaScript-ViewState-Parser/
The parser should work with most non-encrypted ViewStates. It doesn’t
handle the serialization format used by .NET version 1 because that
version is sorely outdated and therefore too unlikely to be
encountered in any real situation.
http://deadliestwebattacks.com/2011/05/29/javascript-viewstate-parser/
Parsing .NET ViewState
A Spirited Peek into ViewState, Part I:
http://deadliestwebattacks.com/2011/05/13/a-spirited-peek-into-viewstate-part-i/
A Spirited Peek into ViewState, Part II:
http://deadliestwebattacks.com/2011/05/25/a-spirited-peek-into-viewstate-part-ii/
Here's another decoder that works well as of 2014: http://viewstatedecoder.azurewebsites.net/
This worked on an input on which the Ignatu decoder failed with "The serialized data is invalid" (although it leaves the BinaryFormatter-serialized data undecoded, showing only its length).
This is somewhat "native" .NET way of converting ViewState from string into StateBag
Code is below:
public static StateBag LoadViewState(string viewState)
{
System.Web.UI.Page converterPage = new System.Web.UI.Page();
HiddenFieldPageStatePersister persister = new HiddenFieldPageStatePersister(new Page());
Type utilClass = typeof(System.Web.UI.BaseParser).Assembly.GetType("System.Web.UI.Util");
if (utilClass != null && persister != null)
{
MethodInfo method = utilClass.GetMethod("DeserializeWithAssert", BindingFlags.NonPublic | BindingFlags.Static);
if (method != null)
{
PropertyInfo formatterProperty = persister.GetType().GetProperty("StateFormatter", BindingFlags.NonPublic | BindingFlags.Instance);
if (formatterProperty != null)
{
IStateFormatter formatter = (IStateFormatter)formatterProperty.GetValue(persister, null);
if (formatter != null)
{
FieldInfo pageField = formatter.GetType().GetField("_page", BindingFlags.NonPublic | BindingFlags.Instance);
if (pageField != null)
{
pageField.SetValue(formatter, null);
try
{
Pair pair = (Pair)method.Invoke(null, new object[] { formatter, viewState });
if (pair != null)
{
MethodInfo loadViewState = converterPage.GetType().GetMethod("LoadViewStateRecursive", BindingFlags.Instance | BindingFlags.NonPublic);
if (loadViewState != null)
{
FieldInfo postback = converterPage.GetType().GetField("_isCrossPagePostBack", BindingFlags.NonPublic | BindingFlags.Instance);
if (postback != null)
{
postback.SetValue(converterPage, true);
}
FieldInfo namevalue = converterPage.GetType().GetField("_requestValueCollection", BindingFlags.NonPublic | BindingFlags.Instance);
if (namevalue != null)
{
namevalue.SetValue(converterPage, new NameValueCollection());
}
loadViewState.Invoke(converterPage, new object[] { ((Pair)((Pair)pair.First).Second) });
FieldInfo viewStateField = typeof(Control).GetField("_viewState", BindingFlags.NonPublic | BindingFlags.Instance);
if (viewStateField != null)
{
return (StateBag)viewStateField.GetValue(converterPage);
}
}
}
}
catch (Exception ex)
{
if (ex != null)
{
}
}
}
}
}
}
}
return null;
}
You can ignore the URL field and simply paste the viewstate into the Viewstate string box.
It does look like you have an old version; the serialisation methods changed in ASP.NET 2.0, so grab the 2.0 version
Best way in python is use this link.
A small Python 3.5+ library for decoding ASP.NET viewstate.
First install that: pip install viewstate
>>> from viewstate import ViewState
>>> base64_encoded_viewstate = '/wEPBQVhYmNkZQ9nAgE='
>>> vs = ViewState(base64_encoded_viewstate)
>>> vs.decode()
('abcde', (True, 1))
Online Viewstate Viewer made by Lachlan Keown:
http://lachlankeown.blogspot.com/2008/05/online-viewstate-viewer-decoder.html
Normally, ViewState should be decryptable if you have the machine-key, right? After all, ASP.net needs to decrypt it, and that is certainly not a black box.

Resources