object to struct with as operator

Because as operator returns null if type check fails:

The expression of the form E as T where E is an expression that returns a value and T is the name of a type or a type parameter, produces the same result as: E is T ? (T)(E) : (T)null except that E is only evaluated once.

Which can't be done if T is non-nullable value type (so compiler emits the error). Using nullable value type as T will work:

object actionData = new Hex(); // your code returning boxed Hex
Hex? hex = actionData as Hex?;
if(hex.HasValue)
{
   ...
}

Case 1

Assuming that the result of GetData() is of correct the correct type (ie something that is castable to the Hex struct the following will successfully compile and also work at runtime

struct Hex { ...} 
...
Hex foo = (Hex)GetData(); 

because you can always write an explicit cast (ie you are telling the compiler you know what you are doing and it shouldn't care about possible incompatibilities)

Case 2

If the result of GetData() is something, that isn't castable to Hex the same code

struct Hex { ...} 
...
Hex foo = (Hex)GetData(); 

will still successfully compile (because you are overruling the compiler). But it will throw an InvalidCastException at runtime.

Case 3

Your second snippet won't even compile. Because the result of the as operator is nullable (ie as returns null if the typecheck fails) and you cannot assign null to a non-nullable struct.

struct Hex { ...} 
...
Hex hex = actionData as Hex;

If you want to be able to compile this, you have to make the variable nullable like

Hex? hex = actionData as Hex?;
if (hex.HasValue) {
  ... //conversion succeeded
} else {
  ... //conversion failed and hex is null
}

or you make Hex a class instead of a struct. Because a class is a reference type which can also be null, but a struct is a value type which cannot be null.